跳转至

REST API

:22222/api/* 暴露 41 个 HTTP 接口,全部 JSON。

完整参数级文档

本页是概览. 每个 endpoint 的完整参数 / 返回结构 / 错误码见 API 参考 → REST API (v1.4.85 新增, 70 route × 9 section).

调用形式

# 不带鉴权(本地开发)
curl http://localhost:22222/api/accounts

# Bearer Token 鉴权
curl -H "Authorization: Bearer fc_xxxx..." http://localhost:22222/api/accounts

# 大部分写接口用 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]}'

路由表

系统

方法 路径 Scope 用途
GET /api/global-state qot:read 全局状态(服务器时间、市场状态)
GET /api/user-info qot:read 当前用户信息
GET /api/delay-statistics qot:read 协议延迟统计

行情

方法 路径 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 澄清)

外部 v1.4.71 报告 BUG-012:"订阅成功但 /api/sub-infosub_info_list=[]" 是 per-connection 设计。差别:

  • GET /api/sub-info只返当前连接自己发的订阅(REST 每次请求 是独立 HTTP 连接 → 通常查到空)。响应字段 is_own_conn_data: true 暗示此语义。适合 "我刚发的订阅还在吗" 快速自检。
  • POST /api/query-subscription(v1.4.74 加)— body 可传 is_req_all_conn: true所有连接的订阅(跨 HTTP 连接 + WebSocket + MCP 等全局视图)。 适合 "daemon 内还订阅了哪些" 审计 / 多客户端部署场景。

推荐:生产环境查订阅状态用 /api/query-subscription + is_req_all_conn=true 避免 per-conn 误解。/api/sub-info 保留作 REST 快速 liveness 探测。

交易

方法 路径 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

运维

方法 路径 Scope 用途
GET /metrics Prometheus 抓取
GET /health liveness probe
GET /ws qot:read(握手) WebSocket 推送升级
GET /api/admin/status admin (v1.4.32+) daemon 健康快照(登录 / broker 通道 / cipher 就绪度)
POST /api/admin/reload admin (v1.4.32+) 清 cipher 缓存 + v1.4.47 刷新磁盘凭据
POST /api/admin/shutdown admin (v1.4.32+) 优雅退出 daemon(1 秒内)

错误码

HTTP 含义
200 成功
400 body JSON 格式错 / 必填字段缺
401 没带 Bearer / token 无效 / 过期
403 scope 不够
404 路径不在路由表(fail-closed,不漏信息)
429 限额触发(rate / daily / per-order / 市场白名单 / 时段等)
500 服务端 bug / 网关 disconnect

错误 body 统一:

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

请求 body 格式

路由层接 Json<Value> 然后交给 adapter::proto_request,里面把 JSON 转 protobuf 调 RequestRouter。所以 body 结构 和 Futu protobuf 定义完全一致 —— 直接看 proto/ 目录下的 .proto 文件。

字段名一定是 snake_case,不是 camelCase

Rust prost + serde 默认把 Proto 源里 camelCase 字段名(trdEnv / accID / trdMarket)自动转成 snake_case(trd_env / acc_id / trd_market)。REST JSON 层只认 snake_case

用错字段名时 serde 默认静默忽略(无 deny_unknown_fields)→ daemon 返回 HTTP 200 但 s2c: null,看起来像"成功但无数据"—— 这是 一个极易踩的坑。如果看到 s2c: null,第一步查字段名大小写。

三种 body 模式

所有 POST 接口的 body 都是 {"c2s": {...}} 包一层,c2s 里的字段按类型分三种:

1) 带 TrdHeader 的交易 / 账户类(funds / positions / orders / unlock-trade 等)

{
  "c2s": {
    "header": { "trd_env": 1, "acc_id": 123456789012345678, "trd_market": 1 }
  }
}

2) 带 security_list 的行情类(quote / subscribe / snapshot 等)

{
  "c2s": {
    "security_list": [{ "market": 11, "code": "AAPL" }],
    "sub_type_list": [1, 6]
  }
}

3) 带单个 security 的(kline / ticker / rt / orderbook 等)

{
  "c2s": {
    "security": { "market": 1, "code": "00700" },
    "kl_type": 2
  }
}

市场枚举(两套,别混)

  • 行情 marketQot_Common.QotMarket):1=HK 11=US 21=SH 22=SZ 31=SG 41=JP 42=AU 81=FX
  • 交易 trd_marketTrd_Common.TrdMarket):1=HK 2=US 3=CN 4=HKCC 5=FUTURES 6=SG 7=JP

从 WS push 消息的 sec_key 字段能反推出是哪套:"11_AAPL" / "1_00700" 前缀就是 market

下单的 body 结构(proto/Trd_PlaceOrder.proto 的 C2S):

{
  "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
}

主要 enum 值(与 Futu 官方 Trd_Common.proto 一致,协议兼容):

  • trd_env:1 = 模拟,2 = 真实
  • 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(限价),2 = MARKET,5 = ABSOLUTE_LIMIT,6 = AUCTION,7 = AUCTION_LIMIT,8 = SPECIAL_LIMIT

参考实现

真实调用样例可以参考: