arbitrage-engine/docs/ai/03-api-contracts.md
fanziqi 22787b3e0a docs: add AI documentation suite and comprehensive code review report
- 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
2026-03-03 19:01:18 +08:00

243 lines
6.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
generated_by: repo-insight
version: 1
created: 2026-03-03
last_updated: 2026-03-03
source_commit: 0d9dffa
coverage: 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) or `http://localhost:8000` (local).
- Auth: Bearer JWT in `Authorization` header. Two public endpoints (`/api/health`, `/api/rates`) need no token.
- Token lifecycle: access token 24 h, refresh token 7 d; use `POST /api/refresh` to renew.
- Registration is invite-code gated: must supply a valid `invite_code` in 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`
```json
// 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`
```json
// 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`
```json
// Request
{ "refresh_token": "<token>" }
// Response 200
{ "access_token": "<new_jwt>", "token_type": "bearer" }
// Errors: 401 (expired/revoked)
```
#### `POST /api/logout`
```json
// Request header: Authorization: Bearer <access_token>
// Request body: { "refresh_token": "<token>" }
// Response 200: { "ok": true }
```
#### `GET /api/me`
```json
// Auth required
// Response 200
{ "id": 1, "email": "...", "role": "user", "created_at": "..." }
```
### Public Endpoints (no auth)
#### `GET /api/health`
```json
{ "status": "ok", "timestamp": "2026-03-03T12:00:00" }
```
#### `GET /api/rates`
Returns live Binance premiumIndex for BTCUSDT, ETHUSDT, XRPUSDT, SOLUSDT. Cached 3 s.
```json
{
"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.
```json
{
"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.
```json
{
"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.
```json
{
"BTC": { "annualized": 12.5, "count": 150 },
"ETH": { ... }
}
```
#### `GET /api/snapshots?hours=24&limit=5000`
Rate snapshots from local PG.
```json
{
"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`
```json
{
"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.
```json
{
"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.
```json
{
"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.
```json
{
"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 strategy
- `GET /api/paper/trades` — paper trade history
- `GET /api/paper/trades/v52` — v52 paper trade history
- `GET /api/live/trades` — live trade history
- `GET /api/live/config` — current live config
- `GET /api/live/events` — live trading event log
- `GET /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:
```json
{ "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_URL` env 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/register` exact field validation (password min length, etc.) not confirmed.
- [risk] No rate limiting visible on public endpoints; `/api/rates` with 3 s cache could be bypassed by direct calls.
## Source Refs
- `backend/main.py:101-298` — all confirmed REST endpoints
- `backend/auth.py:23` — auth router prefix
- `backend/main.py:16-21` — CORS config
- `frontend/lib/api.ts:90-116` — client-side API wrappers
- `frontend/lib/auth.tsx``authFetch` with auto-refresh (not fully read)