Skip to content

快速開始

本套接口為標準 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_timelisting_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

bash
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"
        }'

響應示例:

json
{
  "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 後,開發者需要生成並臨時保存 statecode_verifier,再自行拼接授權 URL,引導用戶在瀏覽器中打開並完成授權。

code_verifier 應為高熵隨機字符串;code_challengecode_verifier 計算得到:

text
code_challenge = BASE64URL-ENCODE(SHA256(code_verifier))

請將 statecode_verifier 臨時保存到當前授權會話中,後續回調校驗和換取 Token 時會用到。

請求地址:

text
GET https://webapi.moomoo.com/oauth2/authorize/confirm

該地址是瀏覽器授權頁地址。用戶會在授權頁完成登錄、選擇授權範圍並授權;開發者無需直接調用後端內部授權接口。

Query 參數:

參數是否必填示例值說明來源
client_id4a8bcd69-e915-4778-9583-17ad0e9e6a80OAuth 客戶端 ID,用於標識當前應用註冊 OAuth 客戶端接口返回
code_challengestlSAHmH-iuYaK76djkKQpu7Jk1uAh_Dq09M_EYXDXkPKCE 校驗值,用於防止授權碼被攔截後濫用code_verifier 計算得到,計算方式為 BASE64URL-ENCODE(SHA256(code_verifier))
code_challenge_methodS256code_challenge 的計算方式固定傳 S256
redirect_urihttp://localhost:60355/callback用戶授權完成後的回調地址必須與註冊 OAuth 客戶端時傳入的 redirect_uris 之一完全一致
response_typecodeOAuth 響應類型固定傳 code
state{random_state}防止 CSRF 攻擊的隨機字符串,也可用於保存業務上下文由開發者生成,並在回調時校驗是否一致

拼接並編碼後的授權 URL 示例(為便於閱讀,按參數換行展示;實際訪問時請去掉換行和縮進):

text
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 請求,並在查詢參數中攜帶 codestate

text
http://localhost:60355/callback?code={authorization_code}&state={state}

你的應用只需要按普通 HTTP 請求處理:

  1. 監聽 localhost:60355/callback 路由。
  2. 從 query 中讀取 codestate
  3. 校驗回調中的 state 是否等於發起授權前保存的值。
  4. 校驗通過後,把 code 和之前保存的 code_verifier 傳給第三步換取 Token。

偽代碼:

text
on GET /callback:
  code = query["code"]
  state = query["state"]

  if state != saved_state:
    return "invalid state"

  使用 code 和 saved_code_verifier 換取 Token

authorization_code 只能用於換取 Token,不是調用 OpenAPI 的訪問令牌。授權碼有效期為 5 分鐘,且只能成功使用一次;請在收到回調後立即換取 Token,過期或重複使用都需要重新發起授權。

第三步:使用授權碼換取 Token

Body 參數:

參數是否必填示例值說明
grant_typeauthorization_code固定傳 authorization_code
code{authorization_code}授權回調中返回的授權碼
client_id4a8bcd69-e915-4778-9583-17ad0e9e6a80OAuth 客戶端 ID
redirect_urihttp://localhost:60355/callback必須與授權 URL 中的 redirect_uri 完全一致
code_verifier{code_verifier}生成 code_challenge 時使用的原始隨機字符串

請求示例:

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

響應示例:

json
{
  "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_inaccess_token 有效期,單位為秒
refresh_token刷新令牌,用於在 access_token 過期後換取新的 access_token
scope用戶已授權的權限範圍,多個 scope 以空格分隔

第四步:刷新 Access Token

access_token 過期時,可以使用 refresh_token 換取新的 access_token

Body 參數:

參數是否必填示例值說明
grant_typerefresh_token固定傳 refresh_token
refresh_token{refresh_token}換取 Token 時返回的刷新令牌
client_id4a8bcd69-e915-4778-9583-17ad0e9e6a80OAuth 客戶端 ID

請求示例:

bash
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

響應示例:

json
{
  "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:

text
Authorization: Bearer {access_token}

不需要再計算請求籤名,也不需要在 REST API 請求中額外傳入 client_id。服務端會從 access_token 中識別用戶、OAuth 客戶端和授權範圍,並根據當前接口所需權限進行校驗。

以下以查詢港股交易日曆為例:

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

參數說明:

參數位置示例值說明
marketQueryHK市場前綴
startQuery2025-12-22起始日期,格式 yyyy-MM-dd
endQuery2025-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 連接,等價表達式如下:

text
{timestamp_ms} + "\n" +
{http_method} + "\n" +
{request_path} + "\n" +
{query_string} + "\n" +
{body_part}

不要省略中間的換行符。即使 query_stringbody_part 為空,也要保留對應字段位置和字段之間的 \n

字段說明:

字段說明
timestamp_ms當前毫秒時間戳,對應請求頭 X-Timestamp
http_methodHTTP 方法,使用大寫,例如 GETPOST
request_pathURL 路徑,不包含域名和查詢參數,例如 /api/v1.0/quote/trading-days
query_string最終請求中的原始查詢串,不包含開頭的 ?;沒有查詢參數時傳空字符串
body_part請求原始 body 字節的 SHA256 小寫十六進制摘要;沒有請求體時傳空字符串

簽名必須基於最終發出的請求內容:query_string 的參數順序和 URL 編碼要與實際請求完全一致;body_part 使用原始請求體字節計算,不要重新格式化 JSON 後再計算。

以查詢港股交易日曆為例:

text
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 請求沒有請求體,精確的簽名原文為:

text
1782357937000\nGET\n/api/v1.0/quote/trading-days\nmarket=HK&start=2025-12-22&end=2025-12-26\n

按行展開後是:

text
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-KeyAppKey ID
AuthorizationBase64 編碼後的簽名結果。AppKey 場景請直接填寫簽名字符串,不要添加 Bearer 前綴
X-Timestamp客戶端當前毫秒時間戳,需與簽名原文中的 timestamp_ms 一致
X-Nonce客戶端隨機字符串,用於防重放;僅支持字母、數字、下劃線和連字符,長度 1-64

以下使用 AppKey 方式調用交易日曆接口:

bash
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 錯誤碼。客戶端可以通過以下接口獲取服務端時間戳

bash
curl -X GET https://webapi.moomoo.com/api/v1.0/server-time

Response
{"server_time_ms":"1782971427455"}

通用約定

  • 證券標識{market}.{code},如 HK.00700US.AAPL
  • 時間:多為 Unix 毫秒時間戳,部分秒級;日期字段為標的市場時區 YYYY-MM-DD
  • 比率:百分比數值(1.23 表示 1.23%)。
  • 分頁:列表類接口用 next_key / limit,詳見 分頁約定

下一步