Skip to content

REST API

:22222/api/* exposes 41 HTTP endpoints, all JSON.

Full parameter-level reference

This page is an overview. For per-endpoint full parameters / return structures / error codes, see API Reference → REST API (new in v1.4.85, 70 routes × 9 sections).

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/query-subscription qot:read
POST /api/used-quota 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

/api/sub-info vs /api/query-subscription (v1.4.84 clarification)

External v1.4.71 BUG-012 report: "subscribe succeeds but /api/sub-info returns sub_info_list=[]" is per-connection by design:

  • GET /api/sub-info — returns subscriptions for current connection only (each REST call is a separate HTTP connection → usually empty). Response field is_own_conn_data: true indicates this scope. Use for quick "is my subscription alive" self-check.
  • POST /api/query-subscription (added in v1.4.74) — body can pass is_req_all_conn: true to query all connections (global view across HTTP + WebSocket + MCP clients). Use for "what subscriptions exist daemon-wide" audit / multi-client deployments.

Recommendation: production subscription status queries should use /api/query-subscription with is_req_all_conn: true to avoid per-connection confusion. /api/sub-info remains for REST quick liveness probes.

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
GET /api/admin/status admin (v1.4.32+) daemon health snapshot
POST /api/admin/reload admin (v1.4.32+) drop cipher cache + v1.4.47 refresh credentials
POST /api/admin/shutdown admin (v1.4.32+) graceful daemon exit (within 1s)

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:

{"error": "limit check failed: rate limit exceeded: 3 orders in the last 60s (cap 3)"}

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 = real
  • trd_side: 1 = BUY, 2 = SELL, 3 = SELL_SHORT, 4 = BUY_BACK
  • trd_market: 1 = HK, 2 = US, 3 = CN, 4 = HKCC, 5 = FUTURES, 6 = SG, 7 = JP
  • order_type: 1 = NORMAL (limit), 2 = MARKET, 5 = ABSOLUTE_LIMIT, 6 = AUCTION, 7 = AUCTION_LIMIT, 8 = SPECIAL_LIMIT

Reference implementations

Working call examples live in: