Skip to content

Authentication

Every OpenAPI request must be authenticated. This page explains the supported authentication methods, environment variable configuration, and token refresh mechanism.

Authentication Methods

OpenAPI supports two authentication methods:

OAuth 2.0 is a modern authentication method using Bearer Tokens. No HMAC signing is needed — it's more secure and convenient.

Step 1: Register an OAuth Client

Run the following command to register an OAuth client and obtain a client_id:

bash
curl -X POST https://openapi.futunn.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 Futu OpenAPI"
        }'

Response example:

json
{
  "client_id": "72d9caaf-0bd4-4000-85a7-8c7978c74544",
  "client_id_issued_at": 1773311221,
  "client_secret_expires_at": 1773314821,
  "client_name": "My Futu OpenAPI",
  "redirect_uris": ["http://localhost:60355/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "token_endpoint_auth_method": "none",
  "response_types": ["code"],
  "registration_access_token": "BVlMLEtNUUu4FoRFNItC2FfeR/rLpqLNyEuCJNNTCWE=",
  "registration_client_uri": "https://openapi.futunn.com/oauth2/register/72d9caaf-0bd4-4000-85a7-8c7978c74544"
}

Save the client_id for later use.

Step 2: Authorize and Obtain Token

The SDK provides built-in OAuth support. Use OAuthBuilder to complete the browser authorization flow, then use Config.from_oauth() to create the configuration. Tokens are automatically persisted and refreshed on expiry.

Token storage path: macOS/Linux: ~/.futu/openapi/tokens/<client_id>, Windows: %USERPROFILE%\.futu\openapi\tokens\<client_id>.

Python

python
from futu.openapi import Config, OAuthBuilder

oauth = OAuthBuilder("your-client-id").build(
    lambda url: print(f"Please visit this URL to authorize: {url}")
)
config = Config.from_oauth(oauth)

JavaScript

javascript
const { Config, OAuth } = require('@futu/openapi')

const oauth = await OAuth.build('your-client-id', (_, url) => {
  console.log('Please visit this URL to authorize: ' + url)
})
const config = Config.fromOAuth(oauth)

OAuth Advantages

  • More secure (no shared secrets)
  • Simpler (no signature computation)
  • Modern token-based authentication
  • Automatic token persistence and refresh

:::caution Token Security OAuth Tokens should be stored securely in your application (e.g., encrypted files, secure keychain). Do not store them in environment variables. :::

Method 2: Traditional API Key (Legacy)

Obtaining App Key, App Secret, and Access Token

Sign in to the Developer Portal and navigate to User Center.

The page will display your Application Credentials (App Key, App Secret, Access Token). Note that this Access Token is a legacy API Key credential, which is different from the access token returned by OAuth.

:::caution Protect your Access Token carefully — anyone who obtains it can trade on your account via OpenAPI! :::

Environment Variables

Traditional API Key credentials (only 3 required):

VariableDescription
FUTU_APP_KEYApp Key obtained from the portal
FUTU_APP_SECRETApp Secret obtained from the portal
FUTU_ACCESS_TOKENAccess Token obtained from the Developer Portal (User Center → Application Credentials)

Other environment variables:

NameDescription
FUTU_HTTP_URLHTTP API endpoint (default: https://openapi.futunn.com)
FUTU_QUOTE_WS_URLQuote WebSocket endpoint
FUTU_TRADE_WS_URLTrade WebSocket endpoint
FUTU_LANGUAGELanguage identifier: zh-CN, zh-HK, or en (default: en)
FUTU_REGIONOverride access point. SDK auto-selects based on network; set manually if incorrect
FUTU_LOG_PATHLog file path (default: no logging)

About Environment Variables

Environment variables are not mandatory. If setting them is inconvenient, you can initialize directly in code with parameters. The SDK Config can use Config.from_env() to create from environment variables, or Config.new(app_key, app_secret, access_token) with explicit parameters.

macOS / Linux

Open a terminal and run:

bash
export FUTU_APP_KEY="Your App Key"
export FUTU_APP_SECRET="Your App Secret"
export FUTU_ACCESS_TOKEN="Your Access Token"

Windows

Using CMD:

bash
C:\Users\user> setx FUTU_APP_KEY "Your App Key"
SUCCESS: Specified value was saved.

C:\Users\user> setx FUTU_APP_SECRET "Your App Secret"
SUCCESS: Specified value was saved.

C:\Users\user> setx FUTU_ACCESS_TOKEN "Your Access Token"
SUCCESS: Specified value was saved.

:::caution Windows Environment Variables After running the commands above, you need to restart Windows or log out and back in for the variables to take effect. :::

After restarting, verify with:

bash
C:\Users\user> set FUTU
FUTU_APP_KEY=xxxxxxx
FUTU_APP_SECRET=xxxxxx
FUTU_ACCESS_TOKEN=xxxxxxx

Request Signature

When using traditional API Key, each HTTP request is signed with HMAC-SHA256 over the canonical string METHOD\nPATH\nTIMESTAMP\nBODY using your App Secret as the key. The resulting signature is sent in the X-Api-Signature header:

http
POST /v1/quote/snapshot HTTP/1.1
Host: openapi.futunn.com
X-Api-Key: {appKey}
X-Api-Timestamp: 1714032000
X-Api-Signature: {hmacSha256Hex}
Authorization: Bearer {accessToken}
Content-Type: application/json

Timestamps older than 60 seconds are rejected to mitigate replay attacks.

Refreshing the Access Token

INFO

This section applies to traditional API Key authentication only. OAuth 2.0 tokens are refreshed automatically by the SDK.

The traditional API Key Access Token expires after 90 days by default. Call the refresh method before expiry to obtain a new token, then update your FUTU_ACCESS_TOKEN.

Python

python
from datetime import datetime, timedelta
from futu.openapi import Config

config = Config.from_env()
# Set expiry to 3 years from now
new_token = config.refresh_access_token(
    expired_at=datetime.now() + timedelta(days=365 * 3)
)
print("New Access Token:", new_token)

JavaScript

javascript
const { Config } = require('@futu/openapi')

const config = Config.fromEnv()
const expiredAt = new Date()
expiredAt.setFullYear(expiredAt.getFullYear() + 3)
const newToken = await config.refreshAccessToken(expiredAt)
console.log('New Access Token:', newToken)

The expired_at parameter specifies the new token's expiry time (default: 90 days from now).

Revoking Credentials

If a credential is leaked, revoke it immediately from the Developer Portal. Revocation takes effect within 30 seconds across all endpoints.

See Also