REST API¶
:22222/api/* exposes 41 HTTP endpoints, all JSON.
Call format¶
# without auth (local dev)
curl http://localhost:22222/api/accounts
# with Bearer Token
curl -H "Authorization: Bearer fc_xxxx..." http://localhost:22222/api/accounts
# most write endpoints take POST + JSON body
curl -X POST http://localhost:22222/api/quote \
-H 'Content-Type: application/json' \
-d '{"security_list":[{"market":1,"code":"00700"}],"sub_type_list":[1]}'
Routing table¶
System¶
| Method | Path | Scope | Purpose |
|---|---|---|---|
| GET | /api/global-state |
qot:read | Global state (server time, market status) |
| GET | /api/user-info |
qot:read | Current user info |
| GET | /api/delay-statistics |
qot:read | Protocol latency stats |
Quote¶
| Method | Path | Scope |
|---|---|---|
| POST | /api/subscribe |
qot:read |
| GET | /api/sub-info |
qot:read |
| POST | /api/quote |
qot:read |
| POST | /api/kline |
qot:read |
| POST | /api/orderbook |
qot:read |
| POST | /api/broker |
qot:read |
| POST | /api/ticker |
qot:read |
| POST | /api/rt |
qot:read |
| POST | /api/snapshot |
qot:read |
| POST | /api/static-info |
qot:read |
| POST | /api/plate-set |
qot:read |
| POST | /api/plate-security |
qot:read |
| POST | /api/reference |
qot:read |
| POST | /api/owner-plate |
qot:read |
| POST | /api/option-chain |
qot:read |
| POST | /api/warrant |
qot:read |
| POST | /api/capital-flow |
qot:read |
| POST | /api/capital-distribution |
qot:read |
| POST | /api/user-security |
qot:read |
| POST | /api/stock-filter |
qot:read |
| POST | /api/ipo-list |
qot:read |
| POST | /api/future-info |
qot:read |
| POST | /api/market-state |
qot:read |
| POST | /api/history-kline |
qot:read |
Trade¶
| Method | Path | Scope |
|---|---|---|
| GET | /api/accounts |
acc:read |
| POST | /api/sub-acc-push |
acc:read |
| POST | /api/funds |
acc:read |
| POST | /api/positions |
acc:read |
| POST | /api/orders |
acc:read |
| POST | /api/order-fills |
acc:read |
| POST | /api/max-trd-qtys |
acc:read |
| POST | /api/history-orders |
acc:read |
| POST | /api/history-order-fills |
acc:read |
| POST | /api/margin-ratio |
acc:read |
| POST | /api/order-fee |
acc:read |
| POST | /api/unlock-trade |
trade:real |
| POST | /api/order |
trade:real |
| POST | /api/modify-order |
trade:real |
Ops¶
| Method | Path | Scope | Purpose |
|---|---|---|---|
| GET | /metrics |
none | Prometheus scrape |
| GET | /health |
none | Liveness probe |
| GET | /ws |
qot:read (handshake) | WebSocket push upgrade |
HTTP status codes¶
| HTTP | Meaning |
|---|---|
| 200 | Success |
| 400 | Malformed JSON body / missing required field |
| 401 | Bearer missing / token invalid / expired |
| 403 | Scope insufficient |
| 404 | Path not in the routing table (fail-closed — no info leak) |
| 429 | Limit tripped (rate / daily / per-order / market whitelist / time window / ...) |
| 500 | Server bug / gateway disconnect |
Error body is uniform:
Request body shape¶
The routing layer receives Json<Value> and hands it off to
adapter::proto_request, which converts JSON → protobuf and calls
RequestRouter. So the body shape matches the Futu protobuf definitions
verbatim — read the .proto files under proto/ for truth.
Place-order body (C2S section of proto/Trd_PlaceOrder.proto):
{
"packet_id": { "conn_id": 12345, "serial_no": 1 },
"header": { "trd_env": 1, "acc_id": 987654, "trd_market": 1 },
"trd_side": 1,
"order_type": 1,
"code": "00700",
"qty": 100,
"price": 300.0,
"sec_market": 1
}
Main enum values (identical to Futu's Trd_Common.proto, protocol-compatible):
trd_env: 1 = simulate, 2 = realtrd_side: 1 = BUY, 2 = SELL, 3 = SELL_SHORT, 4 = BUY_BACKtrd_market: 1 = HK, 2 = US, 3 = CN, 4 = HKCC, 5 = FUTURES, 6 = SG, 7 = JPorder_type: 1 = NORMAL (limit), 2 = MARKET, 5 = ABSOLUTE_LIMIT, 6 = AUCTION, 7 = AUCTION_LIMIT, 8 = SPECIAL_LIMIT
Reference implementations¶
Working call examples live in:
- Quick start — curl snippets
- Case: browser frontend — TypeScript client code
- Case: automated trading bot — Python gRPC code (same call pattern as REST)