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

6.6 KiB
Raw Blame History

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) 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

// 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 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:

{ "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.tsxauthFetch with auto-refresh (not fully read)