快速開始
本套接口為標準 REST / HTTP,任意語言用 HTTP 客戶端即可調用,無需安裝專用 SDK。
API Host
- HTTP API —
https://webapi.moomoo.com - WebSocket Quote —
wss://webapi-quote.moomoo.com - WebSocket Trade —
wss://webapi-trade.moomoo.com
INFO
時間字段多為 Unix 毫秒時間戳(如 update_time、listing_date),部分為秒級(如 wrt_maturity_date);data_date 等日期為標的市場時區的 YYYY-MM-DD。
選擇認證方式
moomoo OpenAPI 支持兩種認證方式。推薦優先使用方式一:OAuth 2.1 + PKCE。
| 認證方式 | 推薦程度 | 適用場景 | 請求認證方式 |
|---|---|---|---|
| 方式一:OAuth 2.1 + PKCE | 推薦 | 第三方應用、用戶授權、需要代表用戶訪問賬戶或交易資源 | Authorization: Bearer {access_token} |
| 方式二:傳統 API Key | 兼容 | 服務端自有系統、後端任務、兼容傳統接入方式 | X-Api-Key + Authorization: {signature_base64} |
方式一:OAuth 2.1 + PKCE(推薦)
OAuth 2.1 + PKCE 是推薦認證方式。它使用 Bearer Token 調用接口,無需保存 API 私鑰,也無需為每個 REST 請求計算簽名。
適用場景
適合第三方應用、桌面應用、移動端應用、Web 應用等需要用戶授權的場景。
第一步:註冊 OAuth 客戶端
執行以下命令註冊 OAuth 客戶端,獲取 client_id:
curl -X POST https://webapi.moomoo.com/oauth2/register \
-H "Content-Type: application/json" \
-d '{
"redirect_uris": ["http://localhost:60355/callback"],
"token_endpoint_auth_method": "none",
"grant_types": ["authorization_code","refresh_token"],
"response_types": ["code"],
"client_name": "My moomoo OpenAPI"
}'響應示例:
{
"client_id": "4a8bcd69-e915-4778-9583-17ad0e9e6a80",
"client_id_issued_at": 1782357937,
"client_name": "My moomoo OpenAPI",
"redirect_uris": ["http://localhost:60355/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"token_endpoint_auth_method": "none",
"response_types": ["code"],
"registration_access_token": "2827551884d13cbed3ea58280b44765a56eae0cca39587b732bda239b322a35a",
"registration_client_uri": "https://webapi.moomoo.com/oauth2/register/4a8bcd69-e915-4778-9583-17ad0e9e6a80",
"scope": "quote:read quote:write trade:read trade:write accid:*",
"pkce_required": true
}保存 client_id 供後續使用。
第二步:引導用戶授權並獲取授權碼
獲取 client_id 後,開發者需要生成並臨時保存 state 和 code_verifier,再自行拼接授權 URL,引導用戶在瀏覽器中打開並完成授權。
code_verifier 應為高熵隨機字符串;code_challenge 由 code_verifier 計算得到:
code_challenge = BASE64URL-ENCODE(SHA256(code_verifier))請將 state 和 code_verifier 臨時保存到當前授權會話中,後續回調校驗和換取 Token 時會用到。
請求地址:
GET https://webapi.moomoo.com/oauth2/authorize/confirm該地址是瀏覽器授權頁地址。用戶會在授權頁完成登錄、選擇授權範圍並授權;開發者無需直接調用後端內部授權接口。
Query 參數:
| 參數 | 是否必填 | 示例值 | 說明 | 來源 |
|---|---|---|---|---|
client_id | 是 | 4a8bcd69-e915-4778-9583-17ad0e9e6a80 | OAuth 客戶端 ID,用於標識當前應用 | 註冊 OAuth 客戶端接口返回 |
code_challenge | 是 | stlSAHmH-iuYaK76djkKQpu7Jk1uAh_Dq09M_EYXDXk | PKCE 校驗值,用於防止授權碼被攔截後濫用 | 由 code_verifier 計算得到,計算方式為 BASE64URL-ENCODE(SHA256(code_verifier)) |
code_challenge_method | 是 | S256 | code_challenge 的計算方式 | 固定傳 S256 |
redirect_uri | 是 | http://localhost:60355/callback | 用戶授權完成後的回調地址 | 必須與註冊 OAuth 客戶端時傳入的 redirect_uris 之一完全一致 |
response_type | 是 | code | OAuth 響應類型 | 固定傳 code |
state | 是 | {random_state} | 防止 CSRF 攻擊的隨機字符串,也可用於保存業務上下文 | 由開發者生成,並在回調時校驗是否一致 |
拼接並編碼後的授權 URL 示例(為便於閱讀,按參數換行展示;實際訪問時請去掉換行和縮進):
https://webapi.moomoo.com/oauth2/authorize/confirm?
client_id=4a8bcd69-e915-4778-9583-17ad0e9e6a80&
code_challenge=stlSAHmH-iuYaK76djkKQpu7Jk1uAh_Dq09M_EYXDXk&
code_challenge_method=S256&
redirect_uri=http%3A%2F%2Flocalhost%3A60355%2Fcallback&
response_type=code&
state={random_state}授權回調:
redirect_uri 是你的應用提供的 HTTP 接收地址,不是 OpenAPI 接口。以 http://localhost:60355/callback 為例,用戶完成授權後,瀏覽器會向你的應用發起一次 GET 請求,並在查詢參數中攜帶 code 和 state:
http://localhost:60355/callback?code={authorization_code}&state={state}你的應用只需要按普通 HTTP 請求處理:
- 監聽
localhost:60355的/callback路由。 - 從 query 中讀取
code和state。 - 校驗回調中的
state是否等於發起授權前保存的值。 - 校驗通過後,把
code和之前保存的code_verifier傳給第三步換取 Token。
偽代碼:
on GET /callback:
code = query["code"]
state = query["state"]
if state != saved_state:
return "invalid state"
使用 code 和 saved_code_verifier 換取 Tokenauthorization_code 只能用於換取 Token,不是調用 OpenAPI 的訪問令牌。授權碼有效期為 5 分鐘,且只能成功使用一次;請在收到回調後立即換取 Token,過期或重複使用都需要重新發起授權。
第三步:使用授權碼換取 Token
Body 參數:
| 參數 | 是否必填 | 示例值 | 說明 |
|---|---|---|---|
grant_type | 是 | authorization_code | 固定傳 authorization_code |
code | 是 | {authorization_code} | 授權回調中返回的授權碼 |
client_id | 是 | 4a8bcd69-e915-4778-9583-17ad0e9e6a80 | OAuth 客戶端 ID |
redirect_uri | 是 | http://localhost:60355/callback | 必須與授權 URL 中的 redirect_uri 完全一致 |
code_verifier | 是 | {code_verifier} | 生成 code_challenge 時使用的原始隨機字符串 |
請求示例:
curl -X POST https://webapi.moomoo.com/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code={authorization_code}" \
-d "client_id=4a8bcd69-e915-4778-9583-17ad0e9e6a80" \
-d "redirect_uri=http://localhost:60355/callback" \
-d "code_verifier={code_verifier}"響應示例:
{
"access_token": "xxxx",
"token_type": "Bearer",
"expires_in": 7200,
"refresh_token": "yyyy",
"scope": "quote:read trade:read accid:123456"
}響應字段:
| 字段 | 說明 |
|---|---|
access_token | 用於調用 OpenAPI 的訪問令牌 |
token_type | 固定為 Bearer |
expires_in | access_token 有效期,單位為秒 |
refresh_token | 刷新令牌,用於在 access_token 過期後換取新的 access_token |
scope | 用戶已授權的權限範圍,多個 scope 以空格分隔 |
第四步:刷新 Access Token
當 access_token 過期時,可以使用 refresh_token 換取新的 access_token。
Body 參數:
| 參數 | 是否必填 | 示例值 | 說明 |
|---|---|---|---|
grant_type | 是 | refresh_token | 固定傳 refresh_token |
refresh_token | 是 | {refresh_token} | 換取 Token 時返回的刷新令牌 |
client_id | 是 | 4a8bcd69-e915-4778-9583-17ad0e9e6a80 | OAuth 客戶端 ID |
請求示例:
curl -X POST https://webapi.moomoo.com/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "refresh_token={refresh_token}" \
-d "client_id=4a8bcd69-e915-4778-9583-17ad0e9e6a80"以上為 Public Client + PKCE 主流程。若使用 token_endpoint_auth_method=client_secret_post 的 Confidential Client,刷新時還需要在 Body 中傳入 client_secret。
響應示例:
{
"access_token": "zzzz",
"token_type": "Bearer",
"expires_in": 7200,
"scope": "quote:read trade:read accid:123456"
}刷新時不會輪換 refresh_token;請繼續安全保存原 refresh_token。
第五步:調用 REST API
拿到 access_token 後,後續 REST API 請求只需要通過 Authorization 請求頭攜帶 Bearer Token:
Authorization: Bearer {access_token}不需要再計算請求籤名,也不需要在 REST API 請求中額外傳入 client_id。服務端會從 access_token 中識別用戶、OAuth 客戶端和授權範圍,並根據當前接口所需權限進行校驗。
以下以查詢港股交易日曆為例:
curl -X GET "https://webapi.moomoo.com/api/v1.0/quote/trading-days?market=HK&start=2025-12-22&end=2025-12-26" \
-H "Authorization: Bearer {access_token}"參數說明:
| 參數 | 位置 | 示例值 | 說明 |
|---|---|---|---|
market | Query | HK | 市場前綴 |
start | Query | 2025-12-22 | 起始日期,格式 yyyy-MM-dd |
end | Query | 2025-12-26 | 結束日期,格式 yyyy-MM-dd |
如果 access_token 過期或無效,請使用 refresh_token 刷新後重試;如果返回權限不足,請確認用戶授權的 scope 是否覆蓋當前接口。
OAuth 優勢
- 無需保存 API 私鑰
- 無需為每個 REST 請求計算簽名
- 基於 Token 授權,更適合用戶授權給第三方應用的場景
Token 安全
OAuth Token 應安全存儲在應用程序中(如加密文件、安全密鑰鏈),不要存儲在環境變量中。
方式二:傳統 API Key(兼容)
傳統 API Key 主要用於兼容已有服務端接入方式。每次調用 REST API 前,需要使用私鑰對請求內容簽名。
適用場景
適合服務端自有系統、後端定時任務、內部工具等由開發者自行管理密鑰的場景。
第一步:創建 AppKey
請登錄 https://open.moomoo.com/dashboard,進入用戶中心,創建 AppKey 並上傳公鑰。創建 AppKey 時需要選擇簽名算法,並在本地安全保存對應私鑰。
傳統 API Key 使用非對稱密鑰簽名認證。創建 AppKey 時需要選擇簽名算法並上傳對應公鑰;客戶端調用 API 時使用本地私鑰對請求內容簽名,服務端會根據 AppKey 查詢公鑰和算法後完成驗籤。
當前支持的簽名算法:
| 算法 | 說明 |
|---|---|
Ed25519 | 使用 Ed25519 私鑰直接對簽名原文簽名 |
RSA-SHA256 | 使用 RSA 私鑰按 PKCS#1 v1.5 + SHA256 對簽名原文簽名 |
私鑰安全
私鑰只應保存在開發者自己的安全環境中,請勿上傳到平臺、提交到代碼倉庫,或以明文形式寫入日誌和配置文件。
第二步:構造簽名
每次調用 REST API 前,需要使用 AppKey 對應的私鑰對本次請求內容簽名。簽名原文由 5 個字段組成,字段之間必須使用換行符 \n 連接,等價表達式如下:
{timestamp_ms} + "\n" +
{http_method} + "\n" +
{request_path} + "\n" +
{query_string} + "\n" +
{body_part}不要省略中間的換行符。即使 query_string 或 body_part 為空,也要保留對應字段位置和字段之間的 \n。
字段說明:
| 字段 | 說明 |
|---|---|
timestamp_ms | 當前毫秒時間戳,對應請求頭 X-Timestamp |
http_method | HTTP 方法,使用大寫,例如 GET、POST |
request_path | URL 路徑,不包含域名和查詢參數,例如 /api/v1.0/quote/trading-days |
query_string | 最終請求中的原始查詢串,不包含開頭的 ?;沒有查詢參數時傳空字符串 |
body_part | 請求原始 body 字節的 SHA256 小寫十六進制摘要;沒有請求體時傳空字符串 |
簽名必須基於最終發出的請求內容:query_string 的參數順序和 URL 編碼要與實際請求完全一致;body_part 使用原始請求體字節計算,不要重新格式化 JSON 後再計算。
以查詢港股交易日曆為例:
GET https://webapi.moomoo.com/api/v1.0/quote/trading-days?market=HK&start=2025-12-22&end=2025-12-26如果 timestamp_ms=1782357937000,該 GET 請求沒有請求體,精確的簽名原文為:
1782357937000\nGET\n/api/v1.0/quote/trading-days\nmarket=HK&start=2025-12-22&end=2025-12-26\n按行展開後是:
1782357937000
GET
/api/v1.0/quote/trading-days
market=HK&start=2025-12-22&end=2025-12-26
<空 body_part>其中最後一個 \n 用於連接 query_string 和空的 body_part。簽名後,將簽名字節做 Base64 編碼,作為 Authorization 請求頭的值。
算法使用:
| 算法 | 簽名方式 |
|---|---|
Ed25519 | 使用 Ed25519 私鑰直接簽名上述簽名原文 |
RSA-SHA256 | 先對簽名原文計算 SHA256,再使用 RSA 私鑰按 PKCS#1 v1.5 簽名 |
第三步:調用 REST API
調用 REST API 時需要攜帶以下認證信息:
| Header | 是否必填 | 說明 |
|---|---|---|
X-Api-Key | 是 | AppKey ID |
Authorization | 是 | Base64 編碼後的簽名結果。AppKey 場景請直接填寫簽名字符串,不要添加 Bearer 前綴 |
X-Timestamp | 是 | 客戶端當前毫秒時間戳,需與簽名原文中的 timestamp_ms 一致 |
X-Nonce | 是 | 客戶端隨機字符串,用於防重放;僅支持字母、數字、下劃線和連字符,長度 1-64 |
以下使用 AppKey 方式調用交易日曆接口:
curl -X GET "https://webapi.moomoo.com/api/v1.0/quote/trading-days?market=HK&start=2025-12-22&end=2025-12-26" \
-H "X-Api-Key: {app_key}" \
-H "X-Timestamp: {timestamp_ms}" \
-H "X-Nonce: {nonce}" \
-H "Authorization: {signature_base64}"其中 {timestamp_ms} 必須使用當前毫秒時間戳,並與第二步簽名原文中的 timestamp_ms 保持一致;{signature_base64} 是第二步簽名結果的 Base64 編碼。服務端會根據 X-Api-Key 查詢已上傳的公鑰和簽名算法,並用同樣的簽名原文完成驗籤。
如果客戶端時間戳與服務端時間戳偏移量超過閾值(默認 5 秒),接口會返回 -12006 錯誤碼。客戶端可以通過以下接口獲取服務端時間戳
curl -X GET https://webapi.moomoo.com/api/v1.0/server-time
Response
{"server_time_ms":"1782971427455"}通用約定
- 證券標識:
{market}.{code},如HK.00700、US.AAPL。 - 時間:多為 Unix 毫秒時間戳,部分秒級;日期字段為標的市場時區
YYYY-MM-DD。 - 比率:百分比數值(
1.23表示 1.23%)。 - 分頁:列表類接口用
next_key/limit,詳見 分頁約定。