- Generate full AI-consumable docs (docs/ai/): system overview, architecture, module cheatsheet, API contracts, data model, build guide, decision log, glossary, and open questions (deep tier coverage) - Add PROBLEM_REPORT.md: categorized bug/risk summary - Add DETAILED_CODE_REVIEW.md: full line-by-line review of all 15 backend files, documenting 4 fatal issues, 5 critical deployment bugs, 4 security vulnerabilities, and 6 architecture defects with prioritized fix plan
6.6 KiB
| generated_by | version | created | last_updated | source_commit | coverage |
|---|---|---|---|---|---|
| repo-insight | 1 | 2026-03-03 | 2026-03-03 | 0d9dffa |
standard |
03 — API Contracts
Purpose
Documents all REST API endpoints, authentication requirements, request/response shapes, and error conventions.
TL;DR
- Base URL:
https://arb.zhouyangclaw.com(prod) orhttp://localhost:8000(local). - Auth: Bearer JWT in
Authorizationheader. Two public endpoints (/api/health,/api/rates) need no token. - Token lifecycle: access token 24 h, refresh token 7 d; use
POST /api/refreshto renew. - Registration is invite-code gated: must supply a valid
invite_codein register body. - All timestamps are Unix epoch (seconds or ms depending on field; see per-endpoint notes).
- Funding rates are stored as decimals (e.g.
0.0001= 0.01%). Frontend multiplies by 10000 for "万分之" display. - Error responses: standard FastAPI
{"detail": "..."}with appropriate HTTP status codes.
Canonical Facts
Authentication
POST /api/register
// Request
{
"email": "user@example.com",
"password": "...",
"invite_code": "XXXX"
}
// Response 200
{
"access_token": "<jwt>",
"refresh_token": "<token>",
"token_type": "bearer",
"user": { "id": 1, "email": "...", "role": "user" }
}
// Errors: 400 (invite invalid/expired), 409 (email taken)
POST /api/login
// Request
{
"email": "user@example.com",
"password": "..."
}
// Response 200
{
"access_token": "<jwt>",
"refresh_token": "<token>",
"token_type": "bearer",
"user": { "id": 1, "email": "...", "role": "user" }
}
// Errors: 401 (invalid credentials), 403 (banned)
POST /api/refresh
// Request
{ "refresh_token": "<token>" }
// Response 200
{ "access_token": "<new_jwt>", "token_type": "bearer" }
// Errors: 401 (expired/revoked)
POST /api/logout
// Request header: Authorization: Bearer <access_token>
// Request body: { "refresh_token": "<token>" }
// Response 200: { "ok": true }
GET /api/me
// Auth required
// Response 200
{ "id": 1, "email": "...", "role": "user", "created_at": "..." }
Public Endpoints (no auth)
GET /api/health
{ "status": "ok", "timestamp": "2026-03-03T12:00:00" }
GET /api/rates
Returns live Binance premiumIndex for BTCUSDT, ETHUSDT, XRPUSDT, SOLUSDT. Cached 3 s.
{
"BTC": {
"symbol": "BTCUSDT",
"markPrice": 65000.0,
"indexPrice": 64990.0,
"lastFundingRate": 0.0001,
"nextFundingTime": 1234567890000,
"timestamp": 1234567890000
},
"ETH": { ... },
"XRP": { ... },
"SOL": { ... }
}
Protected Endpoints (Bearer JWT required)
GET /api/history
7-day funding rate history from Binance. Cached 60 s.
{
"BTC": [
{ "fundingTime": 1234567890000, "fundingRate": 0.0001, "timestamp": "2026-03-01T08:00:00" }
],
"ETH": [ ... ], "XRP": [ ... ], "SOL": [ ... ]
}
GET /api/stats
7-day funding rate statistics. Cached 60 s.
{
"BTC": { "mean7d": 0.01, "annualized": 10.95, "count": 21 },
"ETH": { ... },
"combo": { "mean7d": 0.009, "annualized": 9.85 }
}
// mean7d in %; annualized = mean * 3 * 365 * 100
GET /api/stats/ytd
Year-to-date annualized stats. Cached 3600 s.
{
"BTC": { "annualized": 12.5, "count": 150 },
"ETH": { ... }
}
GET /api/snapshots?hours=24&limit=5000
Rate snapshots from local PG.
{
"count": 43200,
"hours": 24,
"data": [
{ "ts": 1709000000, "btc_rate": 0.0001, "eth_rate": 0.00008, "btc_price": 65000, "eth_price": 3200 }
]
}
GET /api/kline?symbol=BTC&interval=1h&limit=500
Candlestick bars derived from rate_snapshots. Rates scaled by ×10000.
interval:1m,5m,30m,1h,4h,8h,1d,1w,1M
{
"symbol": "BTC",
"interval": "1h",
"count": 24,
"data": [
{
"time": 1709000000,
"open": 1.0, "high": 1.2, "low": 0.8, "close": 1.1,
"price_open": 65000, "price_high": 65500, "price_low": 64800, "price_close": 65200
}
]
}
GET /api/signals/history?limit=100
Legacy signal log from signal_logs table.
{
"items": [
{ "id": 1, "symbol": "BTCUSDT", "rate": 0.0001, "annualized": 10.95, "sent_at": "2026-03-01T08:00:00", "message": "..." }
]
}
GET /api/trades/meta
aggTrades collection status.
{
"BTC": { "last_agg_id": 123456789, "last_time_ms": 1709000000000, "updated_at": "2026-03-03 12:00:00" }
}
GET /api/trades/summary?symbol=BTC&start_ms=0&end_ms=0&interval=1m
Aggregated OHLCV from agg_trades via PG native aggregation.
{
"symbol": "BTC",
"interval": "1m",
"count": 60,
"data": [
{ "bar_ms": 1709000000000, "buy_vol": 10.5, "sell_vol": 9.3, "trade_count": 45, "vwap": 65000.0, "max_qty": 2.5 }
]
}
Signal V52 Endpoints (inferred from frontend routes)
GET /api/signals/v52— signals for v52_8signals strategyGET /api/paper/trades— paper trade historyGET /api/paper/trades/v52— v52 paper trade historyGET /api/live/trades— live trade historyGET /api/live/config— current live configGET /api/live/events— live trading event logGET /api/server/stats— server process stats (psutil)
Auth Header Format
Authorization: Bearer <access_token>
Frontend auto-injects via authFetch() in lib/auth.tsx. On 401, attempts token refresh before retry.
Error Shape
All errors follow FastAPI default:
{ "detail": "Human-readable error message" }
Common HTTP status codes: 400 (bad request), 401 (unauthorized), 403 (forbidden/banned), 404 (not found), 422 (validation error), 502 (Binance upstream error).
Interfaces / Dependencies
- Binance USDC-M Futures REST:
https://fapi.binance.com/fapi/v1/premiumIndex,/fundingRate - CORS allowed origins:
https://arb.zhouyangclaw.com,http://localhost:3000,http://localhost:3001 NEXT_PUBLIC_API_URLenv var controls the frontend base URL (empty = same-origin)
Unknowns & Risks
- [inference] Full endpoint list for signals-v52, paper-v52, live, server pages not confirmed by reading main.py lines 300+. The full saved output contains more routes.
- [inference]
POST /api/registerexact field validation (password min length, etc.) not confirmed. - [risk] No rate limiting visible on public endpoints;
/api/rateswith 3 s cache could be bypassed by direct calls.
Source Refs
backend/main.py:101-298— all confirmed REST endpointsbackend/auth.py:23— auth router prefixbackend/main.py:16-21— CORS configfrontend/lib/api.ts:90-116— client-side API wrappersfrontend/lib/auth.tsx—authFetchwith auto-refresh (not fully read)