# Longbridge Developers Documentation # Index # SDK
:::warning Package Renamed The SDK package has been renamed from `longport` to `longbridge`. The old `longport` package is deprecated. If you were previously using `longport`, please uninstall it before installing the new package. :::
## Longbridge OpenAPI SDK for Python [https://github.com/longbridge/openapi/tree/master/python](https://github.com/longbridge/openapi/tree/master/python) ### Install SDK You can install the SDK via Pip, or directly visit the [PyPI](https://pypi.org/project/longbridge/) page to download. ```bash $ pip install longbridge ``` > NOTE: In macOS system, the `pip` command default is Python 2. You may use `pip3` for use Python 3 version of PyPI. ### API Documents - https://longbridge.github.io/openapi/python/index.html ### Examples - https://github.com/longbridge/openapi/tree/master/examples/python ## Longbridge OpenAPI SDK for Node.js [https://github.com/longbridge/openapi/tree/master/nodejs](https://github.com/longbridge/openapi/tree/master/nodejs) ### Install SDK You can install the SDK via Npm. ```bash $ npm install longbridge --save ``` [https://www.npmjs.com/package/longbridge](https://www.npmjs.com/package/longbridge) ### API Documents - https://longbridge.github.io/openapi/nodejs/index.html ### Examples - https://github.com/longbridge/openapi/tree/master/examples/nodejs ## Longbridge OpenAPI SDK for Rust [https://github.com/longbridge/openapi/tree/master/rust](https://github.com/longbridge/openapi/tree/master/rust) ### Install SDK Add the following line to your `Cargo.toml` file ```toml [dependencies] longbridge = "4.0.5" ``` [https://crates.io/crates/longbridge](https://crates.io/crates/longbridge) ### API Documents - https://longbridge.github.io/openapi/rust/longbridge/index.html ### Examples - https://github.com/longbridge/openapi/tree/master/examples/rust ## Longbridge OpenAPI SDK for Java [https://github.com/longbridge/openapi/tree/master/java](https://github.com/longbridge/openapi/tree/master/java) ### Install SDK Add the following line to your `pom.xml` file ```xml io.github.longbridge openapi-sdk 4.0.5 ``` [https://search.maven.org/artifact/io.github.longbridge/openapi](https://search.maven.org/artifact/io.github.longbridge/openapi) ### API Documents - https://longbridge.github.io/openapi/java/index.html ### Examples - https://github.com/longbridge/openapi/tree/master/examples/java ## Longbridge OpenAPI SDK for Go [https://github.com/longbridge/openapi-go](https://github.com/longbridge/openapi-go) ### Install SDK - Go version >= 1.17 In your project directory, run: ```bash $ go get github.com/longbridge/openapi-go ``` [https://pkg.go.dev/github.com/longbridge/openapi-go](https://pkg.go.dev/github.com/longbridge/openapi-go) ### Examples - https://github.com/longbridge/openapi-go/tree/main/examples ## Longbridge OpenAPI SDK for C/C++ [https://github.com/longbridge/openapi/tree/master/cpp](https://github.com/longbridge/openapi/tree/master/cpp) ### Download - [4.0.5](https://static.lbctrl.com/openapi-sdk/openapi-cpp-sdk-4.0.5.tar.gz) ### API Documents - https://longbridge.github.io/openapi/cpp/index.html ### Examples - https://github.com/longbridge/openapi/tree/master/examples/cpp
# Overview Longbridge Developers provides programmatic interfaces for investors with research and development capabilities, enabling them to build trading or market analysis tools based on their own investment strategies. The platform covers the following categories: - **Quote** — [Real-time and historical quotes](https://longbridge.com/markets), market depth, candlesticks, options/warrants data, subscriptions - **Fundamental** — Company profiles, financials, valuations, analyst ratings, market data, calendars - **News & Contents** — [Market news](https://longbridge.com/en/news), [community topics](https://longbridge.com/topics), sharelist management - **Trade** — Create, amend, and cancel orders; query orders, executions, and assets - **Account** — Portfolio analysis, price alerts, DCA plans, [watchlist](https://longbridge.com/watchlist) - **CLI** — Command-line tool covering all of the above, plus quant backtesting and research - **MCP** — Model Context Protocol integration for AI assistant workflows ## Interface Type Longbridge provides diversified access methods such as HTTP / WebSockets interfaces for accessing the underlying services and SDK (Python / C++, etc.) encapsulated in the upper layer, allowing flexible choices. ## How to Enable OpenAPI 1. Log in to the [Longbridge App](https://longbridge.com/download) to complete the account opening process; 2. Log in to the [longbridge.com](https://longbridge.com) and enter the developer platform, complete the developer verification (OpenAPI permission application), and obtain a token. ## Quote Coverage
Market Symbol
HK Market Securities (including equities, ETFs, Warrants, CBBCs)
Hang Seng Index
US Market Securities (including stocks, ETFs)
Nasdsaq Index
OPRA Options
CN Market Securities (including stocks, ETFs)
Index
## Trading Supported trading functions include: | Market | Stock and ETF | Warrant & CBBC | Options | | --------- | ------------- | -------------- | ------- | | HK Market | ✓ | ✓ | | | US Market | ✓ | ✓ | ✓ | ## Rate Limit {#rate-limit} | Category | Limitation | | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Quote API | | | Trade API | | :::success The [OpenAPI SDK](https://open.longbridge.com/sdk) has done effective frequency control internally: - Quote: The methods under `QuoteContext` will be actively controlled by the SDK according to the server's rate limit. When the request is too fast, the SDK will automatically delay the request. Therefore, you do not need to implement the frequency control details separately. - Trade: The methods under `TradeContext` are not limited by the SDK. Due to the special nature of the trading order placement scenario, this is left to the user to handle. ::: ## Pricing {#pricing} Longbridge does not charge any additional fees for activating or using interface services. You only need to [open a Longbridge Integrated A/C](https://longbridge.com/hk/download) and get OpenAPI service permissions to use it for free. See the [Pricing](/pricing) page for details on quote data subscription fees. For actual transaction fees, please contact the brokerage firm where you have opened your securities account. ## Other The OpenAPI services are provided by Longbridge and the applicable affiliates (subject to the agreement). openapi-trade.longbridge.com ## Assets ### Chunks ## Zh-HK ### Pricing ### Skill #### Install ### Docs #### Socket ##### Protocol #### Screener #### Assets #### Fundamental ##### Fundamental ##### Market #### Ai ##### Chat ##### Workspace #### Quote ##### Pull ##### Push ##### Stocks ##### Security ##### Subscribe ##### Watchlist #### Legal #### Cli ##### Ipo ##### Fundamentals ##### Orders ##### Market-data ##### Quant ##### Watchlist ##### Derivatives ##### Account ##### Content ##### Research #### Market ##### Calendar #### Trade ##### Order ##### Execution ##### Asset #### Qa #### Account ##### Portfolio ##### Dca ##### Alert #### Content ##### Sharelist ##### Topics ##### News ## Pricing ## Pricing ## Skill ## Skill ### Install ### Skill Installation Guide # Longbridge Skill Installation Guide Once installed, you can say things like this to your AI assistant and get real answers: - _"Screen US and HK stocks: market cap above $50B, P/E below 25, recent MACD golden cross — ranked by market cap"_ - _"NVDA just reported — compare actuals vs analyst estimates, break down revenue by segment, and check if valuation is reasonable"_ - _"Set a trailing stop on TSLA: trigger a sell if it drops more than 8%, show me the order details before executing"_ - _"Review my portfolio this month: P&L trend, biggest winner, worst drag, US vs HK allocation"_ - _"Analyze my account and quantify its exposure to AI, semiconductors, and internet-related stocks."_ - _"Based on my 5-year long-term DCA plan, I'm due to buy this month's QQQ and SPY within the next two days. Can you check the recent market conditions and let me know if the timing looks reasonable?"_ --- The quickest way to get started is with a terminal-based AI tool — Claude Code, Codex, opencode, or OpenClaw. Install the CLI, authenticate once, and the AI runs `longbridge` commands on your behalf. If you'd rather not install local software, connect via MCP instead — just add a URL to your AI tool's config. Either way, also install the Skill: a set of instruction files that tells your AI what Longbridge can do and how to use it. --- ## Step 1 — Connect to the Longbridge platform CLI and MCP are both ways to access the Longbridge Developers platform. Pick one: - **CLI** — best experience; the AI runs `longbridge` commands directly in your terminal; requires installing software on your system - **MCP** — easier to connect; just add a URL to your AI tool's config; no local install needed ### Method A — CLI (recommended) Works with Claude Code, Codex (Work locally), opencode, OpenClaw, Gemini CLI, Warp, and any tool that can run shell commands. **Install the CLI:** ```bash # macOS (requires Homebrew — install at https://brew.sh if not already installed) brew install --cask longbridge/tap/longbridge-terminal # macOS / Linux curl -sSL https://open.longbridge.com/longbridge/longbridge-terminal/install | sh ``` **Windows** ([Scoop](https://scoop.sh)): ```powershell scoop install https://open.longbridge.com/longbridge/longbridge-terminal/longbridge.json ``` **Windows** (PowerShell): ```powershell iwr https://open.longbridge.com/longbridge/longbridge-terminal/install.ps1 | iex ``` **Authenticate:** ```bash longbridge auth login ``` Already have a one-time authorization code from [open.longbridge.com/connect](https://open.longbridge.com/connect)? Redeem it directly — no browser needed: ```bash longbridge auth login --auth-code 1234567890 ``` That's it. The AI can now call `longbridge` commands on your behalf. **Claude Code users:** The first time Claude runs a `longbridge` command, it will ask for permission. To allow all Longbridge commands without repeated prompts, add this to `.claude/settings.json` in your project (create the file if it doesn't exist): ```json { "permissions": { "allow": ["Bash(longbridge *)"] } } ``` > See the [CLI reference](/docs/cli) for the full command list and installation details. ### Method B — MCP Works with Claude Desktop, Cursor, Zed, Gemini CLI, Warp, and any tool that supports MCP. Add the following as a remote MCP server in your AI tool: ``` https://mcp.longbridge.com ``` For clients that use a JSON config file (Claude Desktop, Cursor, Zed, Gemini CLI, etc.), add this to your MCP config: ```json { "mcpServers": { "longbridge": { "url": "https://mcp.longbridge.com" } } } ``` > Users in mainland China can use the accelerated endpoint: `https://mcp.longbridge.cn` Where to find the MCP configuration in each client: | Client | Where to configure | | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | | Claude Desktop | Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows) | | Cursor | Settings → MCP Servers → Add Remote MCP Server | | Zed | `context_servers` key in `~/.config/zed/settings.json` | | Gemini CLI | `mcpServers` key in `~/.gemini/settings.json` | | Warp | Settings → AI → MCP Servers → Add | The first time you ask a Longbridge question, your client will open a browser tab for OAuth authorization — no API key required. --- ## Step 2 — Install the Skill The Skill is a set of instruction files that tell your AI assistant what Longbridge can do. **Via Claude Code plugin (recommended for Claude Code users):** In Claude Code, run these two commands: ```text /plugin marketplace add longbridge/skills /plugin install longbridge@longbridge-skills ``` This installs all Longbridge skills through the Claude Code plugin system and keeps them up to date automatically. **Via Codex plugin (recommended for Codex users):** In Codex, run these two commands: ```text codex plugin marketplace add longbridge/skills codex plugin add longbridge@longbridge-skills ``` This installs all Longbridge skills through the Codex plugin system and keeps them up to date automatically. **Via npx / bunx (global install):** ```bash # Node.js npx skills add longbridge/skills -g # Bun bunx skills add longbridge/skills -g ``` > Requires [Node.js](https://nodejs.org) or [Bun](https://bun.sh). **Or download the ZIP and install manually:** Download [longbridge-all.zip](https://open.longbridge.com/skill/longbridge-all.zip) and unzip it, then place the files in your AI tool's Skill directory (Claude Code: `.claude/skills/`, Cursor: paste into the Rules editor, other tools: see the README). **OpenClaw** — send this message in chat and it handles everything automatically: ``` Install the Longbridge Developers Skill from this zip file: https://open.longbridge.com/skill/longbridge-all.zip ``` --- ## Known restrictions by tool Some environments have network whitelists or sandboxing that block CLI installation and MCP server connections. If things aren't working, check here first. ### Claude Desktop — use the Code tab **Chat and Cowork modes** in Claude Desktop have network restrictions that prevent CLI installation and MCP server connections. Do not try to install from either of these modes — it will not work no matter how many times you retry. Switch to the **Code** tab in Claude Desktop (this is Claude Code embedded in the app). From the Code tab, you have full terminal access — you can install the CLI, connect MCP, and install the Skill all in one session. Claude Desktop — switch to the Code tab ### Codex — select "Work locally" Codex in **Cloud** mode has the same network whitelist restrictions. When starting a new session, select **Work locally** instead of Cloud. This gives the agent full access to your shell and network. Codex — select Work locally ### Claude.ai and ChatGPT.com (web) Browser-based interfaces have no access to your local system. They cannot run shell commands or connect to external MCP servers. For Claude, use [Claude Desktop](https://claude.ai/download) and switch to the **Code** tab. --- ## Verify installation After installing, ask your AI assistant: ``` Use Longbridge to get the current quote for AAPL ``` If it returns live data, you're all set. > **Tip:** If the Skill isn't triggered automatically, prefix your request with `/longbridge` to force it — for example: `/longbridge get the current quote for AAPL`. --- ## Troubleshooting **AI says it can't find the Longbridge tool** Some clients require a restart or a new conversation to load the Skill. Confirm the installation is complete, then try again in a new session. **Prompted for authorization when querying data** Run `longbridge auth login` in your terminal and complete the OAuth flow. **Trading operations not working** Confirm your account has OpenAPI trading permissions enabled and is eligible to trade in the target market (HK / US). **Revoking Authorization** To revoke access, go to your Longbridge account → Security Settings → manage authorized apps. ## Zh-CN ### Pricing ### Skill #### Install ### Docs #### Socket ##### Protocol #### Screener #### Assets #### Fundamental ##### Fundamental ##### Market #### Ai ##### Chat ##### Workspace #### Quote ##### Pull ##### Push ##### Stocks ##### Security ##### Subscribe ##### Watchlist #### Legal #### Cli ##### Ipo ##### Fundamentals ##### Orders ##### Market-data ##### Quant ##### Watchlist ##### Derivatives ##### Account ##### Content ##### Research #### Market ##### Calendar #### Trade ##### Order ##### Execution ##### Asset #### Qa #### Account ##### Portfolio ##### Dca ##### Alert #### Content ##### Sharelist ##### Topics ##### News ## Longbridge-terminal ## Docs ## API Reference ## Getting Started ## Foreword Longbridge OpenAPI SDK is implemented based on Rust we have released SDK for Python, Node.js, Rust, C++/C and Java ..., and support for other languages will be launched in the future. ## API Host - HTTP API - `https://openapi.longbridge.com` - WebSocket Quote - `wss://openapi-quote.longbridge.com` - WebSocket Trade - `wss://openapi-trade.longbridge.com` :::tip For access in mainland China, you can use `.cn` domains for better connectivity: - HTTP API - `https://openapi.longbridge.cn` - WebSocket Quote - `wss://openapi-quote.longbridge.cn` - WebSocket Trade - `wss://openapi-trade.longbridge.cn` The SDK automatically selects the access point by network. If the SDK selects incorrectly, set the environment variable `LONGBRIDGE_REGION` (e.g. `cn` or `hk`). ::: ### Access Points and Data Centers Two concepts that are easy to confuse: - **Access point** (`.com` / `.cn`) — network routing only. Both serve identical data and identical auth: a token issued through one is accepted by the other. - **Data center** (`ap` / `us`) — where the account itself lives. It determines which US-only APIs are available. The two cannot be combined freely: | Data center | `.com` | `.cn` | | ------------------------- | ---------------------------------- | ------------- | | `us` (US accounts) | Yes — the only usable access point | Not supported | | `ap` (Longbridge SG / HK) | Yes | Yes | `.cn` has no route to the US data center, so US accounts must always use the `.com` domains — including for login, since the `.cn` login page does not offer US accounts. ## Time Format All API response are used [Unix Timestamp](https://en.wikipedia.org/wiki/Unix_time), timezone is UTC. ## Environment Requirements ## CLI Quick Start If you don't need to write code, the [Longbridge CLI](/docs/cli) offers a lightweight alternative — install once, authorize via OAuth, no environment variables needed. ### Installation ```bash brew install --cask longbridge/tap/longbridge-terminal ``` ```bash curl -sSL https://open.longbridge.com/longbridge/longbridge-terminal/install | sh ``` ```powershell scoop install https://open.longbridge.com/longbridge/longbridge-terminal/longbridge.json ``` ```powershell iwr https://open.longbridge.com/longbridge/longbridge-terminal/install.ps1 | iex ``` ### Login longbridge auth login The browser opens the authorization page automatically. The token is saved after approval — no need to repeat. ## Install SDK :::warning Package Renamed The SDK package has been renamed from `longport` to `longbridge`. The old `longport` package is deprecated. If you were previously using `longport`, please uninstall it before installing the new package. ::: ```bash pip3 install longbridge ``` ```bash yarn add longbridge ``` ```toml [dependencies] longbridge = "4.0.5" tokio = { version = "1", features = "rt-multi-thread" } ``` ```xml io.github.longbridge openapi-sdk 4.0.5 ``` ```shell go get github.com/longbridge/openapi-go ``` Let's take obtaining assets as an example to demonstrate how to use the SDK. ## Configuration 1. [Download App](https://longbridge.com/hk/download) and open an account. 2. Get authentication credentials from [Longbridge Developers](https://open.longbridge.com) official website ### Authentication Methods Longbridge OpenAPI supports two authentication methods: #### Method 1: OAuth 2.0 (Recommended) ⭐ OAuth 2.0 is the modern authentication method that uses Bearer tokens without requiring HMAC signatures, making it more secure and convenient. **Step 1: Register OAuth Client** Run the following command to register an OAuth client and get your `client_id`: ```bash curl -X POST https://openapi.longbridge.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 Longbridge OpenAPI" }' ``` ```powershell $body = @{ redirect_uris = @("http://localhost:60355/callback") token_endpoint_auth_method = "none" grant_types = @("authorization_code", "refresh_token") response_types = @("code") client_name = "My Longbridge OpenAPI" } | ConvertTo-Json Invoke-RestMethod -Method POST ` -Uri "https://openapi.longbridge.com/oauth2/register" ` -ContentType "application/json" ` -Body $body ``` Response example: ```json { "client_id": "72d9caaf-0bd4-4000-85a7-8c7978c74544", "client_id_issued_at": 1773311221, "client_secret_expires_at": 1773314821, "client_name": "My Longbridge 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.longbridge.com/oauth2/register/72d9caaf-0bd4-4000-85a7-8c7978c74544" } ``` Save the `client_id` for later use. **Step 2: Authorize and Get Token** The SDK provides built-in OAuth support. Use `OAuthBuilder` to run the browser flow; after authorization, use `Config.from_oauth()` to create the configuration. The token is persisted automatically and refreshed when expired. **Token storage path:** `~/.longbridge/openapi/tokens/` (macOS/Linux), or `%USERPROFILE%\.longbridge\openapi\tokens\` on Windows. ```python from longbridge.openapi import Config, OAuthBuilder oauth = OAuthBuilder("your-client-id").build( lambda url: print(f"Open this URL to authorize: {url}") ) config = Config.from_oauth(oauth) ``` ```python import asyncio from longbridge.openapi import Config, OAuthBuilder async def main() -> None: oauth = await OAuthBuilder("your-client-id").build_async( lambda url: print(f"Open this URL to authorize: {url}") ) config = Config.from_oauth(oauth) if __name__ == "__main__": asyncio.run(main()) ``` ```javascript const { Config, OAuth } = require('longbridge') const oauth = await OAuth.build('your-client-id', (_, url) => { console.log('Open this URL to authorize: ' + url) }) const config = Config.fromOAuth(oauth) ``` ```rust use std::sync::Arc; use longbridge::{Config, oauth::OAuthBuilder}; #[tokio::main] async fn main() -> Result<(), Box> { let oauth = OAuthBuilder::new("your-client-id") .build(|url| println!("Open this URL to authorize: {url}")) .await?; let config = Arc::new(Config::from_oauth(oauth)); Ok(()) } ``` ```java import com.longbridge.*; public class Main { public static void main(String[] args) throws Exception { String clientId = "your-client-id"; OAuth oauth = new OAuthBuilder(clientId) .build(url -> System.out.println("Open to authorize: " + url)) .get(); try (oauth) { Config config = Config.fromOAuth(oauth); } } } ``` ```go package main import ( "context" "fmt" "log" "github.com/longbridge/openapi-go/config" "github.com/longbridge/openapi-go/oauth" ) func main() { o := oauth.New("your-client-id"). OnOpenURL(func(url string) { fmt.Println("Open this URL to authorize:", url) }) if err := o.Build(context.Background()); err != nil { log.Fatal(err) } conf, err := config.New(config.WithOAuthClient(o)) if err != nil { log.Fatal(err) } _ = conf // use conf for TradeContext or QuoteContext } ``` ```cpp #include #include using namespace longbridge; int main(int argc, char const* argv[]) { const std::string client_id = "your-client-id"; OAuthBuilder(client_id).build( [](const std::string& url) { std::cout << "Open this URL to authorize: " << url << std::endl; }, [](auto res) { if (!res) { std::cout << "authorization failed: " << *res.status().message() << std::endl; return; } Config config = Config::from_oauth(*res); // Use config to create QuoteContext or TradeContext }); std::cin.get(); return 0; } ``` :::tip OAuth Benefits - More secure (no shared secret) - Simpler integration (no signature calculation) - Token-based modern authentication - Better suited for modern applications ::: :::caution Token Security OAuth tokens should be stored securely in your application (e.g., encrypted file, secure keychain), **not in environment variables** for security reasons. ::: #### Method 2: Legacy API Key (Compatible) **_Get App Key, App Secret, Access Token and other information_** Log in at [https://open.longbridge.com/](https://open.longbridge.com/) and open **User Center**. The **application credential** (App Key, App Secret, Access Token) is shown on that page. This Access Token is the **legacy** API Key credential; it is **not** the same as the access token obtained via OAuth or the Refresh Token API. Set these as environment variables for development. ### Environment Variables :::caution Please pay attention to protect your **Access Token** information, anyone who gets it can trade your account through OpenAPI! ::: **API Key credentials (required for legacy API Key):** | Environment Variable | Description | | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | `LONGBRIDGE_APP_KEY` | App key from developer center | | `LONGBRIDGE_APP_SECRET` | App secret from developer center | | `LONGBRIDGE_ACCESS_TOKEN` | Legacy Access Token from [https://open.longbridge.com/](https://open.longbridge.com/) (User Center → application credential). Not the OAuth access token. | **Other environment variables:** | Name | Description | | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | | `LONGBRIDGE_LANGUAGE` | Language identifier, `zh-CN`, `zh-HK` or `en` (Default: `en`) | | `LONGBRIDGE_HTTP_URL` | HTTP endpoint url (Default: `https://openapi.longbridge.com`) | | `LONGBRIDGE_QUOTE_WS_URL` | Quote websocket endpoint url (Default: `wss://openapi-quote.longbridge.com/v2`) | | `LONGBRIDGE_TRADE_WS_URL` | Trade websocket endpoint url (Default: `wss://openapi-trade.longbridge.com/v2`) | | `LONGBRIDGE_REGION` | Override API region; SDK auto-selects by network. Set to `cn` or `hk` if incorrect. | | `LONGBRIDGE_ENABLE_OVERNIGHT` | Enable overnight quote, `true` or `false` (Default: `false`). Overnight quotes are included free in US LV1. US stocks only. | | `LONGBRIDGE_PUSH_CANDLESTICK_MODE` | `realtime` or `confirmed` (Default: `realtime`) | | `LONGBRIDGE_PRINT_QUOTE_PACKAGES` | Print quote packages when connected, `true` or `false` (Default: `true`) | | `LONGBRIDGE_LOG_PATH` | Set the path of the log files (Default: no logs) | :::info The SDK also accepts the legacy `LONGPORT_*` variable names for backward compatibility. ::: We recommend that you set the environment variables. For the convenience of demonstration, these environment variables will be used in the sample code in the documents in the following chapters. :::tip About ENV The ENV variables are **not necessary** conditions, if it is inconvenient to set the ENV variables or encounter problems that are difficult to solve, you can not set the ENV variables, but directly use the parameters in the code to initialize. The `Config` in Longbridge OpenAPI SDK can be created with `Config.from_apikey_env()` (or `Config.fromApikeyEnv()` in Node/Java) when using environment variables, or `Config.from_apikey(app_key, app_secret, access_token)` when passing parameters directly. See the comments in the example code below for "Init config without ENV". ::: #### Set Environment for macOS / Linux Open the terminal and enter the following command: ```bash export LONGBRIDGE_APP_KEY="App Key from user center" export LONGBRIDGE_APP_SECRET="App Secret from user center" export LONGBRIDGE_ACCESS_TOKEN="Access Token from user center" ``` #### Set Environment for Windows Windows is a little more complicated, we provide two methods to set the environment variables. 1. **Through the GUI**: Right click on "My Computer" on the desktop, select "Properties", click "Advanced system settings" in the pop-up window. - Click "Environment Variables" in the pop-up window. - Click "New" in the pop-up window, then enter the environment variable name, such as `LONGBRIDGE_APP_KEY`, `Value` respectively fill in the App Key, App Secret, Access Token obtained from the page. 2. **Through the CMD**: Press the `Win + R` shortcut keys and enter the `cmd` command to start the command line (it is recommended to use [Windows Terminal](https://apps.microsoft.com/store/detail/windows-terminal/9N0DX20HK701) for a better development experience). Enter the following command in the command line to set the environment variable: ```bash C:\Users\jason> setx LONGBRIDGE_APP_KEY "App Key from user center" Success: the specified value has been saved. C:\Users\jason> setx LONGBRIDGE_APP_SECRET "App Secret from user center" Success: the specified value has been saved. C:\Users\jason> setx LONGBRIDGE_ACCESS_TOKEN "Access Token from user center" Success: the specified value has been saved. ``` :::caution Windows ENV Restrictions Windows ENV Restrictions, when the above commands are executed successfully, you need to restart Windows or log out and log in again before you can read it. ::: After logging out or restarting, open the command line again and enter the following command to verify that the environment variables are set correctly: ```bash C:\Users\jason> set LONGBRIDGE LONGBRIDGE_APP_KEY=xxxxxxx LONGBRIDGE_APP_SECRET=xxxxxx LONGBRIDGE_ACCESS_TOKEN=xxxxxxx ``` If it prints the value you just set correctly, then the environment variable is right. ### Refresh Access Token :::info This applies to **Legacy API Key** authentication only. OAuth 2.0 tokens are refreshed automatically by the SDK. ::: The Legacy API Key `Access Token` expires after 90 days by default. Call `Config.refresh_access_token()` to obtain a new token before it expires, then update your stored `LONGBRIDGE_ACCESS_TOKEN` with the returned value. ```python from datetime import datetime, timedelta from longbridge.openapi import Config config = Config.from_apikey("YOUR_APP_KEY", "YOUR_APP_SECRET", "YOUR_ACCESS_TOKEN") # Expire 3 years from now new_token = config.refresh_access_token(expired_at=datetime.now() + timedelta(days=365 * 3)) print("New access token:", new_token) # Use the new token to build a new Config, or persist it as LONGBRIDGE_ACCESS_TOKEN new_config = Config.from_apikey("YOUR_APP_KEY", "YOUR_APP_SECRET", new_token) ``` ```python import asyncio from datetime import datetime, timedelta from longbridge.openapi import Config async def main() -> None: config = Config.from_apikey("YOUR_APP_KEY", "YOUR_APP_SECRET", "YOUR_ACCESS_TOKEN") # Expire 3 years from now new_token = await config.refresh_access_token_async(expired_at=datetime.now() + timedelta(days=365 * 3)) print("New access token:", new_token) # Use the new token to build a new Config, or persist it as LONGBRIDGE_ACCESS_TOKEN new_config = Config.from_apikey("YOUR_APP_KEY", "YOUR_APP_SECRET", new_token) if __name__ == "__main__": asyncio.run(main()) ``` ```javascript const { Config } = require('longbridge') const config = Config.fromApikey('YOUR_APP_KEY', 'YOUR_APP_SECRET', 'YOUR_ACCESS_TOKEN') // Expire 3 years from now const expiredAt = new Date() expiredAt.setFullYear(expiredAt.getFullYear() + 3) const newToken = await config.refreshAccessToken(expiredAt) console.log('New access token:', newToken) // Use the new token to build a new Config, or persist it as LONGBRIDGE_ACCESS_TOKEN const newConfig = Config.fromApikey('YOUR_APP_KEY', 'YOUR_APP_SECRET', newToken) ``` ```rust use longbridge::Config; use time::{Duration, OffsetDateTime}; #[tokio::main] async fn main() -> Result<(), Box> { let config = Config::from_apikey("YOUR_APP_KEY", "YOUR_APP_SECRET", "YOUR_ACCESS_TOKEN")?; // Expire 3 years from now let expired_at = OffsetDateTime::now_utc() + Duration::days(365 * 3); let new_token = config.refresh_access_token(Some(expired_at)).await?; println!("New access token: {}", new_token); // Use the new token to build a new Config, or persist it as LONGBRIDGE_ACCESS_TOKEN let new_config = Config::from_apikey("YOUR_APP_KEY", "YOUR_APP_SECRET", &new_token)?; Ok(()) } ``` ```java import com.longbridge.Config; import java.time.OffsetDateTime; public class Main { public static void main(String[] args) throws Exception { Config config = Config.fromApikey("YOUR_APP_KEY", "YOUR_APP_SECRET", "YOUR_ACCESS_TOKEN"); // Expire 3 years from now OffsetDateTime expiredAt = OffsetDateTime.now().plusYears(3); String newToken = config.refreshAccessToken(expiredAt).get(); System.out.println("New access token: " + newToken); // Use the new token to build a new Config, or persist it as LONGBRIDGE_ACCESS_TOKEN Config newConfig = Config.fromApikey("YOUR_APP_KEY", "YOUR_APP_SECRET", newToken); } } ``` ```cpp #include #include #include using namespace longbridge; int main() { Config config = Config::from_apikey("YOUR_APP_KEY", "YOUR_APP_SECRET", "YOUR_ACCESS_TOKEN"); // Expire 3 years from now (Unix timestamp) int64_t expired_at = static_cast(std::time(nullptr)) + 3LL * 365 * 24 * 3600; config.refresh_access_token(expired_at, [](auto res) { if (!res) { std::cerr << "Error: " << *res.status().message() << std::endl; return; } std::cout << "New access token: " << *res << std::endl; // Use the new token to build a new Config, or persist it as LONGBRIDGE_ACCESS_TOKEN Config new_config = Config::from_apikey("YOUR_APP_KEY", "YOUR_APP_SECRET", *res); }); std::cin.get(); return 0; } ``` The `expired_at` parameter sets when the new token expires (default: **90 days** from now). ## Scene Demonstration ### Get Account Balance Create `account_asset.py` and paste the code below: ```python from longbridge.openapi import TradeContext, Config, OAuthBuilder oauth = OAuthBuilder("your-client-id").build( lambda url: print(f"Open this URL to authorize: {url}") ) config = Config.from_oauth(oauth) # Or use API Key: config = Config.from_apikey_env() # Or without ENV: config = Config.from_apikey("YOUR_APP_KEY", "YOUR_APP_SECRET", "YOUR_ACCESS_TOKEN") ctx = TradeContext(config) resp = ctx.account_balance() print(resp) ``` Run it ```bash python account_asset.py ``` Create `account_asset_async.py` and paste the code below: ```python import asyncio from longbridge.openapi import AsyncTradeContext, Config, OAuthBuilder async def main() -> None: oauth = await OAuthBuilder("your-client-id").build_async( lambda url: print(f"Open this URL to authorize: {url}") ) config = Config.from_oauth(oauth) ctx = AsyncTradeContext.create(config) resp = await ctx.account_balance() print(resp) if __name__ == "__main__": asyncio.run(main()) ``` Run it ```bash python account_asset_async.py ``` Create `account_asset.js` and paste the code below: ```javascript const { Config, TradeContext, OAuth } = require('longbridge') async function main() { const oauth = await OAuth.build('your-client-id', (_, url) => { console.log('Open this URL to authorize: ' + url) }) const config = Config.fromOAuth(oauth) // Or use API Key: const config = Config.fromApikeyEnv() const ctx = TradeContext.new(config) const resp = await ctx.accountBalance() for (const obj of resp) { console.log(obj.toString()) } } main().catch(console.error) ``` Run it ```bash node account_asset.js ``` Create `main.rs` and paste the code below: ```rust use std::sync::Arc; use longbridge::{oauth::OAuthBuilder, trade::TradeContext, Config}; #[tokio::main] async fn main() -> Result<(), Box> { let oauth = OAuthBuilder::new("your-client-id") .build(|url| println!("Open this URL to authorize: {url}")) .await?; let config = Arc::new(Config::from_oauth(oauth)); // Or use API Key: let config = Arc::new(Config::from_apikey_env()?); // Or without ENV: let config = Arc::new(Config::from_apikey("YOUR_APP_KEY", "YOUR_APP_SECRET", "YOUR_ACCESS_TOKEN")?); let (ctx, _) = TradeContext::new(config); let resp = ctx.account_balance(None).await?; println!("{:?}", resp); Ok(()) } ``` Run it ```bash cargo run ``` Create `Main.java` and paste the code below: ```java import com.longbridge.*; import com.longbridge.trade.*; class Main { public static void main(String[] args) throws Exception { String clientId = "your-client-id"; OAuth oauth = new OAuthBuilder(clientId) .build(url -> System.out.println("Open to authorize: " + url)) .get(); try (oauth; Config config = Config.fromOAuth(oauth); TradeContext ctx = TradeContext.create(config)) { // Or use API Key: Config.fromApikeyEnv(); TradeContext.create(config) for (AccountBalance obj : ctx.getAccountBalance().get()) { System.out.println(obj); } } } } ``` Run it ```bash mvn compile exec:exec ``` Create `main.go` and paste the code below: ```go package main import ( "context" "fmt" "log" "github.com/longbridge/openapi-go/config" "github.com/longbridge/openapi-go/oauth" "github.com/longbridge/openapi-go/trade" ) func main() { o := oauth.New("your-client-id"). OnOpenURL(func(url string) { fmt.Println("Open this URL to authorize:", url) }) if err := o.Build(context.Background()); err != nil { log.Fatal(err) } conf, err := config.New(config.WithOAuthClient(o)) // Or use API Key from ENV: config.New() // Or without ENV: config.New(config.WithConfigKey("YOUR_APP_KEY", "YOUR_APP_SECRET", "YOUR_ACCESS_TOKEN")) if err != nil { log.Fatal(err) } tradeContext, err := trade.NewFromCfg(conf) if err != nil { log.Fatal(err) } defer tradeContext.Close() ctx := context.Background() ab, err := tradeContext.AccountBalance(ctx, &trade.GetAccountBalance{}) if err != nil { log.Fatal(err) } fmt.Printf("%+v\n", ab[0]) } ``` Run: ```shell go mod tidy go run ./ ``` Create `account_asset.cpp` and paste the code below: ```cpp #include #include #ifdef WIN32 #include #endif using namespace longbridge; using namespace longbridge::trade; static void run(const OAuth& oauth) { Config config = Config::from_oauth(oauth); TradeContext ctx = TradeContext::create(config); ctx.account_balance([](auto res) { if (!res) { std::cout << "failed: " << *res.status().message() << std::endl; return; } for (const auto& b : *res) { std::cout << b.currency << " " << (double)b.available_cash << std::endl; } }); } int main(int argc, char const* argv[]) { #ifdef WIN32 SetConsoleOutputCP(CP_UTF8); #endif const std::string client_id = "your-client-id"; OAuthBuilder(client_id).build( [](const std::string& url) { std::cout << "Open this URL to authorize: " << url << std::endl; }, [](auto res) { if (!res) { std::cout << "authorization failed: " << *res.status().message() << std::endl; return; } run(*res); }); std::cin.get(); return 0; } ``` Run it ```bash g++ -std=c++17 account_asset.cpp -o account_asset -llongbridge && ./account_asset ``` After running, the output is as follows: ``` [ AccountBalance { total_cash: 503898884.81, max_finance_amount: 0.00, remaining_finance_amount: 501403229.49, risk_level: Some(1), margin_call: 0, currency: "HKD", cash_infos: [ CashInfo { withdraw_cash: 501214985.15, available_cash: 501214985.15, frozen_cash: 584438.25, settling_cash: -3897793.90, currency: "HKD", }, CashInfo { withdraw_cash: -25546.89, available_cash: -25546.89, frozen_cash: 295768.57, settling_cash: 2326.60, currency: "USD", } ] } ] ``` ### Subscribe Quote To subscribe to market data, please check the [Developer Center](https://open.longbridge.com/account) - "Quote authority" is correct - [HK Market](https://longbridge.com/hk/) - BMP basic quotation is unable to subscribe with WebSocket as it has no real-time quote push. - US Market - US LV1 (Only OpenAPI). Before running, visit the [Developer Center](https://open.longbridge.com/dashboard) and ensure that the account has the correct quote level. :::info If you do not have the quotes authority, you can enter "Me - My Quotes - Store" to purchase the authority through the "Longbridge" mobile app. https://longbridge.com/download ::: When you have the correct Quote authority, it might look like this: Create `subscribe_quote.py` and paste the code below: ```python from time import sleep from longbridge.openapi import QuoteContext, Config, OAuthBuilder, SubType, PushQuote def on_quote(symbol: str, quote: PushQuote): print(symbol, quote) oauth = OAuthBuilder("your-client-id").build( lambda url: print(f"Open this URL to authorize: {url}") ) config = Config.from_oauth(oauth) ctx = QuoteContext(config) ctx.set_on_quote(on_quote) ctx.subscribe(["700.HK", "AAPL.US", "TSLA.US", "NFLX.US"], [SubType.Quote]) sleep(30) ``` Run it ```bash python subscribe_quote.py ``` Create `subscribe_quote_async.py` and paste the code below: ```python import asyncio from longbridge.openapi import AsyncQuoteContext, Config, OAuthBuilder, SubType, PushQuote async def on_quote(symbol: str, quote: PushQuote) -> None: print(symbol, quote) async def main() -> None: oauth = await OAuthBuilder("your-client-id").build_async( lambda url: print(f"Open this URL to authorize: {url}") ) config = Config.from_oauth(oauth) ctx = AsyncQuoteContext.create(config, loop_=asyncio.get_running_loop()) ctx.set_on_quote(on_quote) await ctx.subscribe(["700.HK", "AAPL.US", "TSLA.US", "NFLX.US"], [SubType.Quote]) await asyncio.sleep(30) if __name__ == "__main__": asyncio.run(main()) ``` Run it ```bash python subscribe_quote_async.py ``` Create `subscribe_quote.js` and paste the code below: ```javascript const { Config, QuoteContext, SubType, OAuth } = require('longbridge') async function main() { const oauth = await OAuth.build('your-client-id', (_, url) => { console.log('Open this URL to authorize: ' + url) }) const config = Config.fromOAuth(oauth) const ctx = QuoteContext.new(config) ctx.setOnQuote((_, event) => console.log(event.toString())) await ctx.subscribe(['700.HK', 'AAPL.US', 'TSLA.US', 'NFLX.US'], [SubType.Quote]) await new Promise(() => {}) } main().catch(console.error) ``` Run it ```bash node subscribe_quote.js ``` Create `main.rs` and paste the code below: ```rust use std::sync::Arc; use longbridge::{ oauth::OAuthBuilder, quote::{QuoteContext, SubFlags}, Config, }; #[tokio::main] async fn main() -> Result<(), Box> { let oauth = OAuthBuilder::new("your-client-id") .build(|url| println!("Open this URL to authorize: {url}")) .await?; let config = Arc::new(Config::from_oauth(oauth)); let (ctx, mut receiver) = QuoteContext::new(config); ctx.subscribe(["700.HK", "AAPL.US", "TSLA.US", "NFLX.US"], SubFlags::QUOTE) .await?; while let Some(event) = receiver.recv().await { println!("{:?}", event); } Ok(()) } ``` Run it ```bash cargo run ``` Create `Main.java` and paste the code below: ```java import com.longbridge.*; import com.longbridge.quote.*; class Main { public static void main(String[] args) throws Exception { String clientId = "your-client-id"; OAuth oauth = new OAuthBuilder(clientId) .build(url -> System.out.println("Open to authorize: " + url)) .get(); try (oauth; Config config = Config.fromOAuth(oauth); QuoteContext ctx = QuoteContext.create(config)) { ctx.setOnQuote((symbol, quote) -> { System.out.printf("%s\t%s\n", symbol, quote); }); ctx.subscribe(new String[] { "700.HK", "AAPL.US", "TSLA.US", "NFLX.US" }, SubFlags.Quote).get(); Thread.sleep(30000); } } } ``` Run it ```bash mvn compile exec:exec ``` Create file `main.go` and paste the code below: ```go package main import ( "context" "encoding/json" "fmt" "log" "os" "os/signal" "syscall" "time" "github.com/longbridge/openapi-go/config" "github.com/longbridge/openapi-go/quote" ) func main() { // create quote context from environment variables conf, err := config.New() if err != nil { log.Fatal(err) } quoteContext, err := quote.NewFromCfg(conf) if err != nil { log.Fatal(err) return } defer quoteContext.Close() ctx := context.Background() quoteContext.OnQuote(func(pe *quote.PushQuote) { bytes, _ := json.Marshal(pe) fmt.Println(string(bytes)) }) quoteContext.OnDepth(func(d *quote.PushDepth) { bytes, _ := json.Marshal(d) if d.Sequence != 0 { fmt.Print(time.UnixMicro(d.Sequence/1000).Format(time.RFC3339) + " ") } fmt.Println(string(bytes)) }) // Subscribe some symbols err = quoteContext.Subscribe(ctx, []string{"700.HK", "AAPL.US", "NFLX.US"}, []quote.SubType{quote.SubTypeDepth}, true) if err != nil { log.Fatal(err) return } quitChannel := make(chan os.Signal, 1) signal.Notify(quitChannel, syscall.SIGINT, syscall.SIGTERM) <-quitChannel } ``` Run: ```shell go run ./ ``` Create `subscribe_quote.cpp` and paste the code below: ```cpp #include #include #ifdef WIN32 #include #endif using namespace longbridge; using namespace longbridge::quote; static QuoteContext g_ctx; static void run(const OAuth& oauth) { Config config = Config::from_oauth(oauth); g_ctx = QuoteContext::create(config); g_ctx.set_on_quote([](auto event) { std::cout << event->symbol << " last_done=" << (double)event->last_done << " volume=" << event->volume << std::endl; }); std::vector symbols = {"700.HK", "AAPL.US", "TSLA.US", "NFLX.US"}; g_ctx.subscribe(symbols, SubFlags::QUOTE(), [](auto res) { if (!res) { std::cout << "failed to subscribe: " << *res.status().message() << std::endl; } }); } int main(int argc, char const* argv[]) { #ifdef WIN32 SetConsoleOutputCP(CP_UTF8); #endif const std::string client_id = "your-client-id"; OAuthBuilder(client_id).build( [](const std::string& url) { std::cout << "Open this URL to authorize: " << url << std::endl; }, [](auto res) { if (!res) { std::cout << "authorization failed: " << *res.status().message() << std::endl; return; } run(*res); }); std::cin.get(); return 0; } ``` Run it ```bash g++ -std=c++17 subscribe_quote.cpp -o subscribe_quote -llongbridge && ./subscribe_quote ``` After running, the output is as follows: ``` 700.HK PushQuote { last_done: 367.000, open: 362.000, high: 369.400, low: 356.000, timestamp: "2022-06-06T08:10:00Z", volume: 22377421, turnover: 8081883405.000, trade_status: Normal, trade_session: Normal } AAPL.US PushQuote { last_done: 147.350, open: 150.700, high: 151.000, low: 146.190, timestamp: "2022-06-06T11:57:36Z", volume: 3724407, turnover: 550606662.815, trade_status: Normal, trade_session: Pre } NFLX.US PushQuote { last_done: 201.250, open: 205.990, high: 205.990, low: 200.110, timestamp: "2022-06-06T11:57:26Z", volume: 137821, turnover: 27888085.590, trade_status: Normal, trade_session: Pre } ``` ### Submit Order Next, we will do a [submit order](https://open.longbridge.com/docs/trade/order/submit) action, we assume that to buy `700.HK` at 50 HKD and quantity is `100`. > NOTE: In order to prevent a successful test buy, the demo here gives a lower price and avoids the transaction. OpenAPI operations are equivalent to online transactions, please operate with caution, and pay attention to parameter details during development and debugging. Create `submit_order.py` and paste the code below: ```python from decimal import Decimal from longbridge.openapi import TradeContext, Config, OAuthBuilder, OrderSide, OrderType, TimeInForceType oauth = OAuthBuilder("your-client-id").build( lambda url: print(f"Open this URL to authorize: {url}") ) config = Config.from_oauth(oauth) ctx = TradeContext(config) resp = ctx.submit_order( side=OrderSide.Buy, symbol="700.HK", order_type=OrderType.LO, submitted_price=Decimal(50), submitted_quantity=Decimal(200), time_in_force=TimeInForceType.Day, remark="Hello from Python SDK", ) print(resp) ``` Run it ```bash python submit_order.py ``` Create `submit_order_async.py` and paste the code below: ```python import asyncio from decimal import Decimal from longbridge.openapi import AsyncTradeContext, Config, OAuthBuilder, OrderSide, OrderType, TimeInForceType async def main() -> None: oauth = await OAuthBuilder("your-client-id").build_async( lambda url: print(f"Open this URL to authorize: {url}") ) config = Config.from_oauth(oauth) ctx = AsyncTradeContext.create(config) resp = await ctx.submit_order( side=OrderSide.Buy, symbol="700.HK", order_type=OrderType.LO, submitted_price=Decimal(50), submitted_quantity=Decimal(200), time_in_force=TimeInForceType.Day, remark="Hello from Python SDK", ) print(resp) if __name__ == "__main__": asyncio.run(main()) ``` Run it ```bash python submit_order_async.py ``` Create `submit_order.js` and paste the code below: ```javascript const { Config, TradeContext, OrderType, OrderSide, Decimal, TimeInForceType, OAuth } = require('longbridge') async function main() { const oauth = await OAuth.build('your-client-id', (_, url) => { console.log('Open this URL to authorize: ' + url) }) const config = Config.fromOAuth(oauth) const ctx = TradeContext.new(config) const resp = await ctx.submitOrder({ symbol: '700.HK', orderType: OrderType.LO, side: OrderSide.Buy, timeInForce: TimeInForceType.Day, submittedPrice: new Decimal(50), submittedQuantity: new Decimal(200), }) console.log(resp.toString()) } main().catch(console.error) ``` Run it ```bash node submit_order.js ``` Create `main.rs` and paste the code below: ```rust use std::sync::Arc; use longbridge::{ decimal, oauth::OAuthBuilder, trade::{OrderSide, OrderType, SubmitOrderOptions, TimeInForceType, TradeContext}, Config, }; #[tokio::main] async fn main() -> Result<(), Box> { let oauth = OAuthBuilder::new("your-client-id") .build(|url| println!("Open this URL to authorize: {url}")) .await?; let config = Arc::new(Config::from_oauth(oauth)); let (ctx, _) = TradeContext::new(config); let opts = SubmitOrderOptions::new( "700.HK", OrderType::LO, OrderSide::Buy, decimal!(200), TimeInForceType::Day, ) .submitted_price(decimal!(50i32)); let resp = ctx.submit_order(opts).await?; println!("{:?}", resp); Ok(()) } ``` Run it ```bash cargo run ``` Create `Main.java` and paste the code below: ```java import com.longbridge.*; import com.longbridge.trade.*; import java.math.BigDecimal; public class Main { public static void main(String[] args) throws Exception { String clientId = "your-client-id"; OAuth oauth = new OAuthBuilder(clientId) .build(url -> System.out.println("Open to authorize: " + url)) .get(); try (oauth; Config config = Config.fromOAuth(oauth); TradeContext ctx = TradeContext.create(config)) { SubmitOrderOptions opts = new SubmitOrderOptions("700.HK", OrderType.LO, OrderSide.Buy, new BigDecimal(200), TimeInForceType.Day).setSubmittedPrice(new BigDecimal(50)); SubmitOrderResponse resp = ctx.submitOrder(opts).get(); System.out.println(resp); } } } ``` Run it ```bash mvn compile exec:exec ``` Create `main.go` and paste the code below: ```go package main import ( "context" "fmt" "log" "os" "os/signal" "syscall" "github.com/shopspring/decimal" "github.com/longbridge/openapi-go/config" "github.com/longbridge/openapi-go/trade" ) func main() { // create trade context from environment variables conf, err := config.New() if err != nil { log.Fatal(err) } tradeContext, err := trade.NewFromCfg(conf) if err != nil { log.Fatal(err) return } defer tradeContext.Close() // subscribe order status tradeContext.OnTrade(func(ev *trade.PushEvent) { // handle order changing event }) ctx := context.Background() // submit order order := &trade.SubmitOrder{ Symbol: "700.HK", OrderType: trade.OrderTypeLO, Side: trade.OrderSideBuy, SubmittedQuantity: 200, TimeInForce: trade.TimeTypeDay, SubmittedPrice: decimal.NewFromFloat(12), } orderId, err := tradeContext.SubmitOrder(ctx, order) if err != nil { log.Fatal(err) return } fmt.Printf("orderId: %v\n", orderId) quitChannel := make(chan os.Signal, 1) signal.Notify(quitChannel, syscall.SIGINT, syscall.SIGTERM) <-quitChannel } ``` 运行: ```shell go run ./ ``` Create `submit_order.cpp` and paste the code below: ```cpp #include #include #ifdef WIN32 #include #endif using namespace longbridge; using namespace longbridge::trade; static void run(const OAuth& oauth) { Config config = Config::from_oauth(oauth); TradeContext ctx = TradeContext::create(config); SubmitOrderOptions opts{ "700.HK", OrderType::LO, OrderSide::Buy, Decimal(200), TimeInForceType::Day, Decimal(50.0), std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, }; ctx.submit_order(opts, [](auto res) { if (!res) { std::cout << "failed: " << *res.status().message() << std::endl; return; } std::cout << "order id: " << res->order_id << std::endl; }); } int main(int argc, char const* argv[]) { #ifdef WIN32 SetConsoleOutputCP(CP_UTF8); #endif const std::string client_id = "your-client-id"; OAuthBuilder(client_id).build( [](const std::string& url) { std::cout << "Open this URL to authorize: " << url << std::endl; }, [](auto res) { if (!res) { std::cout << "authorization failed: " << *res.status().message() << std::endl; return; } run(*res); }); std::cin.get(); return 0; } ``` Run it ```bash g++ -std=c++17 submit_order.cpp -o submit_order -llongbridge && ./submit_order ``` After running, the output is as follows: ``` SubmitOrderResponse { order_id: "718437534753550336" } ``` ### Get Today Orders Create `today_orders.py` and paste the code below: ```python from longbridge.openapi import TradeContext, Config, OAuthBuilder oauth = OAuthBuilder("your-client-id").build( lambda url: print(f"Open this URL to authorize: {url}") ) config = Config.from_oauth(oauth) ctx = TradeContext(config) resp = ctx.today_orders() print(resp) ``` Run it ```bash python today_orders.py ``` Create `today_orders_async.py` and paste the code below: ```python import asyncio from longbridge.openapi import AsyncTradeContext, Config, OAuthBuilder async def main() -> None: oauth = await OAuthBuilder("your-client-id").build_async( lambda url: print(f"Open this URL to authorize: {url}") ) config = Config.from_oauth(oauth) ctx = AsyncTradeContext.create(config) resp = await ctx.today_orders() print(resp) if __name__ == "__main__": asyncio.run(main()) ``` Run it ```bash python today_orders_async.py ``` Create `today_orders.js` and paste the code below: ```javascript const { Config, TradeContext, OAuth } = require('longbridge') async function main() { const oauth = await OAuth.build('your-client-id', (_, url) => { console.log('Open this URL to authorize: ' + url) }) const config = Config.fromOAuth(oauth) const ctx = TradeContext.new(config) const resp = await ctx.todayOrders() for (const obj of resp) { console.log(obj.toString()) } } main().catch(console.error) ``` Run it ```bash node today_orders.js ``` Create `main.rs` and paste the code below: ```rust use std::sync::Arc; use longbridge::{oauth::OAuthBuilder, trade::TradeContext, Config}; #[tokio::main] async fn main() -> Result<(), Box> { let oauth = OAuthBuilder::new("your-client-id") .build(|url| println!("Open this URL to authorize: {url}")) .await?; let config = Arc::new(Config::from_oauth(oauth)); let (ctx, _) = TradeContext::new(config); let resp = ctx.today_orders(None).await?; for obj in resp { println!("{:?}", obj); } Ok(()) } ``` Run it ```bash cargo run ``` Create `Main.java` and paste the code below: ```java import com.longbridge.*; import com.longbridge.trade.*; class Main { public static void main(String[] args) throws Exception { String clientId = "your-client-id"; OAuth oauth = new OAuthBuilder(clientId) .build(url -> System.out.println("Open to authorize: " + url)) .get(); try (oauth; Config config = Config.fromOAuth(oauth); TradeContext ctx = TradeContext.create(config)) { Order[] orders = ctx.getTodayOrders(null).get(); for (Order order : orders) { System.out.println(order); } } } } ``` Run it ```bash mvn compile exec:exec ``` Create `main.go` and paste the code below: ```go package main import ( "context" "fmt" "log" "github.com/longbridge/openapi-go/config" "github.com/longbridge/openapi-go/trade" ) func main() { // create trade context from environment variables conf, err := config.New() if err != nil { log.Fatal(err) } tradeContext, err := trade.NewFromCfg(conf) if err != nil { log.Fatal(err) } defer tradeContext.Close() ctx := context.Background() // today orders orders, err := tradeContext.TodayOrders(ctx, &trade.GetTodayOrders{}) if err != nil { log.Fatal(err) } for _, order := range orders { fmt.Printf("%+v\n", order) } } ``` Run: ```shell go run ./ ``` Create `today_orders.cpp` and paste the code below: ```cpp #include #include #ifdef WIN32 #include #endif using namespace longbridge; using namespace longbridge::trade; static void run(const OAuth& oauth) { Config config = Config::from_oauth(oauth); TradeContext ctx = TradeContext::create(config); ctx.today_orders(std::nullopt, [](auto res) { if (!res) { std::cout << "failed: " << *res.status().message() << std::endl; return; } for (auto it = res->cbegin(); it != res->cend(); ++it) { std::cout << "order_id=" << it->order_id << " quantity=" << it->quantity << std::endl; } }); } int main(int argc, char const* argv[]) { #ifdef WIN32 SetConsoleOutputCP(CP_UTF8); #endif const std::string client_id = "your-client-id"; OAuthBuilder(client_id).build( [](const std::string& url) { std::cout << "Open this URL to authorize: " << url << std::endl; }, [](auto res) { if (!res) { std::cout << "authorization failed: " << *res.status().message() << std::endl; return; } run(*res); }); std::cin.get(); return 0; } ``` Run it ```bash g++ -std=c++17 today_orders.cpp -o today_orders -llongbridge && ./today_orders ``` After running, the output is as follows: ``` Order { order_id: "718437534753550336", status: NotReported, stock_name: "腾讯控股 1", quantity: 200, executed_quantity: None, price: Some(50.000), executed_price: None, submitted_at: 2022-06-06T12:14:16Z, side: Buy, symbol: "700.HK", order_type: LO, last_done: None, trigger_price: Some(0.000), msg: "", tag: Normal, time_in_force: Day, expire_date: Some(NaiveDate(Date { year: 2022, ordinal: 158 })), updated_at: Some(2022-06-06T12:14:16Z), trigger_at: None, trailing_amount: None, trailing_percent: None, limit_offset: None, trigger_status: None, currency: "HKD", outside_rth: nonce } ``` The above example has fully demonstrated how to use the SDK to access the OpenAPI interface. For more interfaces, please read the [Longbridge Developers Documentation](https://open.longbridge.com/docs) in detail and use them according to different interfaces. ## More Examples We provide the complete code of the above examples in the GitHub repository of Longbridge OpenAPI Python SDK, and we will continue to add or update it later. https://github.com/longbridge/openapi/tree/master/examples ## SDK API Document For detailed SDK API document, please visit: https://longbridge.github.io/openapi/ ## Contact & Feedback If there are any questions or suggestions, please feel free to post an issue on GitHub, we will reply as soon as possible. Or there have a lot old discussion in the GitHub issue, you can search the issue to find the answer. - GitHub: https://github.com/longbridge/developers/issues ## Agent Auth Code # Agent Auth Code Agent Auth Code lets you authorize an AI agent to use Longbridge market data and account capabilities by pasting a short, one-time code into the agent — no long URLs and no waiting browser. You generate the code on the Longbridge authorization page, pick the permissions you want to grant, and hand the code to your AI assistant. The agent redeems it in one step through the CLI or the hosted MCP service. :::tip Generate a code Open [https://open.longbridge.com/connect](https://open.longbridge.com/connect), sign in, select the scopes you need, and click generate. ::: ## When to use it Browser-based OAuth is still the default for most desktop clients. Reach for an Agent Auth Code instead when the standard flow does not work well: - **The client does not render the authorization link** — some chat and agent apps show the long OAuth URL as plain text, so it cannot be clicked. - **No browser is available** — on mobile, in a remote shell, or in a sandboxed agent environment that cannot launch a browser. - **The agent does not stay running** — Device Flow requires the CLI to keep polling while you authorize, but many agents do not hold a process open. A one-time code avoids any polling. For a desktop client that fully supports the browser OAuth flow, the standard [MCP authorization flow](/mcp) is simpler and you do not need a code. ## Steps 1. **Open the authorization page** — go to [https://open.longbridge.com/connect](https://open.longbridge.com/connect). 2. **Sign in** with your Longbridge account. 3. **Select permissions** — choose the scopes (market data, account, trading, etc.) you want to grant. The generated code can only ever carry the scopes you pick here. 4. **Generate the code** — the page produces a short auth code and a ready-to-paste instruction text. 5. **Paste it to your AI agent** — copy the instruction text and send it to your assistant. The agent redeems the code using one of the methods below. The code is valid for **5 minutes** and can be used **once**. ## Redeem via CLI Pass the code to `auth login` with the `--auth-code` flag. Replace the example code with your real one: # Redeem an auth code generated from the connect page longbridge auth login --auth-code 6vYzXq3WbKp9TmHd On success the token is saved to `~/.longbridge/openapi/tokens/` and reused automatically by all subsequent commands — exactly like the browser login. See [Installation](/docs/cli/install) for the full `auth` command reference. ## Redeem via MCP Auth-code redemption runs against a dedicated endpoint, **`https://mcp.longbridge.com/agent`**. This endpoint allows unauthorized connections, and while a session is unauthorized it exposes only the `authenticate` tool. The main endpoint `https://mcp.longbridge.com` is standard OAuth 2.1 only and does not offer `authenticate` — clients that fully support OAuth should use the main endpoint, and `/agent` is the fallback channel for when OAuth is not available. **Flow:** 1. **Configure the `/agent` endpoint** — point your client at `https://mcp.longbridge.com/agent`. The unauthorized session shows just the `authenticate` tool. 2. **Call `authenticate` with the auth code** — tell your assistant something like: "Authenticate the Longbridge MCP session with auth code 1234567890." The agent invokes `authenticate` with that code. 3. **Configure the returned token as a Bearer header** — on success, the tool result returns a token. Follow the instructions in the result to have the client send it as `Authorization: Bearer ` on subsequent requests. The remaining Longbridge MCP tools then become available — no browser redirect required. For Claude Code, re-add the server with the token as a header: ```bash claude mcp add --transport http longbridge https://mcp.longbridge.com --header "Authorization: Bearer " ``` Replace `` with the token returned by `authenticate`. Note this points at the main endpoint `https://mcp.longbridge.com` — once you hold a Bearer token, you connect there directly. ## Security - **Scope is pre-selected on the web** — the code can only grant the permissions you chose on the authorization page; an agent cannot request more than the code carries. - **5-minute TTL** — the code expires 5 minutes after it is generated. - **One-time use** — the code is consumed on first successful redemption and cannot be reused. - **Revocable anytime** — go to your Longbridge account security settings and revoke the **AI Agent** authorization to end access. Follow least privilege: grant only the scopes the current task needs. For any trading-related grant, instruct the agent to confirm with you before placing orders. ## FAQ ### The code has expired Auth codes are valid for 5 minutes. Return to [https://open.longbridge.com/connect](https://open.longbridge.com/connect) and generate a new one, then redeem it promptly. ### The code was already used Each code works only once. If redemption already succeeded earlier, you are authorized — there is no need to redeem again. If you need a fresh session, generate a new code. ### The granted permissions are not enough The code only carries the scopes selected on the authorization page. Generate a new code and select the additional scopes you need, then redeem it again to refresh the session's permissions. ### Connection still fails after redeeming - Confirm your Longbridge account is in good standing and identity verification is complete. - Confirm the scopes you selected cover the action you are attempting (for example, trading requires trading scopes). - For MCP, verify the agent connects to `https://mcp.longbridge.com/agent` to call `authenticate`, then reconnects to `https://mcp.longbridge.com` with the returned `Authorization: Bearer` token. ## MCP # Longbridge MCP Service Longbridge provides a hosted MCP (Model Context Protocol) service that lets you use [Longbridge market data](https://longbridge.com/markets) and account capabilities directly from ChatGPT, AI coding assistants, and other chat tools — without managing API keys manually. :::tip MCP endpoint - Global: `https://mcp.longbridge.com` - Mainland China: `https://mcp.longbridge.cn` (faster access) US accounts must use the global endpoint — `.cn` has no route to the US data center and serves AP accounts (Longbridge SG / HK) only. See [Access Points and Data Centers](/docs/getting-started#access-points-and-data-centers). ::: ## Available capabilities Longbridge MCP exposes 100+ tools across six capability areas. Your client discovers them automatically on connect — no manual configuration. | Capability | Coverage | | --------------------------- | -------------------------------------------------------------------------------------------------- | | **[Real-time market data](https://longbridge.com/markets)** | Quotes, candlesticks, depth, broker queues, trades, intraday capital flow | | **Fundamentals & research** | Company profiles, [dividends](https://longbridge.com/calendar/dividend), valuations, executive holdings, A/H premium, macroeconomic indicators | | **Derivatives** | Option chains, warrant filters, issuers, warrant quotes | | **Account & portfolio** | Balances, positions, cash flow, watchlists and groups | | **Trading** | Place / modify / cancel orders, estimate max purchase quantity | | **Automation** | Price alerts, scheduled DCA (dollar-cost averaging) plans | Actual tool availability depends on your region, account level, and granted OAuth scopes. ## Available tools ## Prerequisites - An active [Longbridge account](https://longbridge.com/hk/download) with onboarding completed, or a paper trading account - Another AI client that supports MCP OAuth 2.1 (see compatibility note below) ## Client setup ChatGPT is the recommended starting point because Longbridge is available directly in ChatGPT Plugins. For other MCP clients, configuration format may vary across client versions; treat your client's official MCP documentation as the source of truth. ### ChatGPT Longbridge is available as an official ChatGPT App. On ChatGPT web, desktop, or mobile: 1. Open **Plugins** 2. Search for `longbridge`, or open the [Longbridge ChatGPT App](https://chatgpt.com/apps/longbridge/asdk_app_6a2baf2fad748191812393c3e00308ef) directly 3. Select **Longbridge** and complete the authorization login ![Search for Longbridge in ChatGPT Plugins](https://assets.lbkrs.com/uploads/aeb84040-b2c7-442d-af46-adfab66297a1/scr-20260707-nbjr.png) ![Authorize the Longbridge ChatGPT App](https://assets.lbkrs.com/uploads/a66bcd75-d747-4259-b684-a689d324716c/scr-20260707-nbno.png) After authorization, prefix every message with `@longbridge` to send it to Longbridge MCP — for example: `@longbridge check my today's orders`. Without this prefix, ChatGPT will not route your question to Longbridge. :::warning Trading features unavailable in ChatGPT Due to ChatGPT platform policies, the Longbridge ChatGPT App does not include order placement and other trading tools. To use trading features, switch to Claude Code, Cursor, or another MCP client. ::: ### Claude Longbridge is available as an official connector in Claude's directory. On [Claude](https://claude.ai) web or Claude Desktop: 1. Click **Customize** → **Connectors**, then click the **Add** button 2. Select **Browser Connectors** from the dropdown and search for `longbridge` 3. Select **Longbridge** and complete the authorization login Or open the [Longbridge connector](https://claude.ai/directory/connectors/longbridge) directly. ### Claude Code Run the following command in your terminal: ```bash claude mcp add --transport http longbridge https://mcp.longbridge.com ``` Then open the `claude` terminal interface, type `/mcp`, select `longbridge`, and choose **Authenticate** to complete the OAuth authorization flow. ### Codex Run the following command in your terminal: ```bash codex mcp add longbridge --url https://mcp.longbridge.com ``` Then follow the OAuth authorization flow in Codex when prompted. #### Codex Desktop 1. Click **Settings** (bottom right) → **MCP Servers** → **Add Server** 2. In the "Connect to a custom MCP" screen, fill in: - Name: `longbridge` - Type: **Streamable HTTP** - URL: `https://mcp.longbridge.com` - Leave all other fields empty 3. Click **Save** 4. Back in the MCP Servers list, click **Authenticate** on the `longbridge` entry to complete OAuth authorization ### Grok Open [Grok Connectors](https://grok.com/connectors) and add a custom MCP server: 1. In the left sidebar, go to **Skills and Connectors** → **Connectors** → **New Connector** → **Custom** 2. Fill in: - Name: `Longbridge` - Server URL: `https://mcp.longbridge.com` 3. Click **Add Connector** and follow the Longbridge OAuth 2 authorization flow to complete the setup ![](https://assets.lbkrs.com/uploads/08d07992-5463-4bfd-a4e4-97fab6e9cb41/grok-0.png) ![](https://assets.lbkrs.com/uploads/56eee753-f3d4-4186-b024-ee0145f4eb54/grok-1.png) ### Cursor Settings → MCP Servers → Add Remote MCP Server, then enter the URL above. ### Zed Add the following to your `settings.json` under the `context_servers` key (key name is customizable): ```json { "mcpServers": { "longbridge": { "url": "https://mcp.longbridge.com" } } } ``` ### Cherry Studio Settings → MCP Servers → Add, then enter the URL above. ### Manus In Manus, open the **Plugins** window, click the **Create** button on the right side, and select **Import MCP by JSON** from the menu. Paste the following JSON to complete the import: ```json { "mcpServers": { "longbridge": { "url": "https://mcp.longbridge.com" } } } ``` ![](https://assets.lbctrl.com/uploads/f3aa3f71-c7a1-48b3-91dc-ea82a7018b53/scr-20260625-ttzy.png) ## OAuth authorization flow Longbridge MCP uses standard OAuth 2.1. You never need to paste API keys or tokens into the client. In ChatGPT, the authorization happens when you add Longbridge from Plugins. In other MCP clients, the first tool call usually starts the browser authorization flow. ``` AI client Browser Longbridge | | | |--- initiate MCP ------->| | | |--- redirect to auth ------>| | |<-- show login & consent ---| | |--- sign in & approve ------>| |<-- return credentials --| | |--- call tools with credentials ----------------------->| ``` **Steps:** 1. **Initiate connection** — Adding the Longbridge MCP config and calling a tool for the first time triggers the authorization flow 2. **Browser redirect** — The client opens a browser tab with the Longbridge login and consent page 3. **Sign in and approve** — Log in with your Longbridge account and review and accept the requested permission scopes 4. **Session established** — After approval, the client receives credentials and MCP tools become available 5. **Credential maintenance** — Credentials are refreshed automatically per OAuth policy; to revoke access, visit Longbridge account security settings ## Client compatibility Longbridge MCP requires clients that fully implement **MCP OAuth 2.1**. Clients with incomplete support will fail during the authorization flow. Known issue: early versions of Cherry Studio do not support the full OAuth flow. Please upgrade to the latest release. If another client fails to connect, check its version and MCP support documentation. :::tip Client can't open the browser? If your client has incomplete OAuth support or cannot launch a browser, use an [Agent Auth Code](/agent-auth) instead: generate a one-time code at [https://open.longbridge.com/connect](https://open.longbridge.com/connect), connect to the dedicated endpoint `https://mcp.longbridge.com/agent`, and have the agent redeem it via the `authenticate` tool. ::: ## Security recommendations - **Least privilege**: Only approve the scopes required for your current task; avoid over-granting - **Trading confirmation**: For any order placement prompt, explicitly instruct the AI to ask for human confirmation before executing - **Credential handling**: OAuth credentials are managed by your client; avoid copying them into untrusted environments - **Regular review**: Periodically check and revoke unused authorizations in your [Longbridge account](https://longbridge.com/hk/download) security settings ## Recommended usage pattern 1. **Start with read-only tools**: Begin with [market data](https://longbridge.com/markets), account overview, and position queries to learn tool behavior at low risk 2. **Gradually enable trading**: Enable order placement only after verifying scope configuration and your own risk controls 3. **Add guardrails in prompts**: For example, "keep each trade under X", "always confirm with me before placing an order" ## Troubleshooting ### OAuth sign-in failed - Confirm your Longbridge account is in good standing and identity verification is complete - Remove the existing MCP configuration from the client and re-add it to trigger a fresh authorization - Check whether the requested scopes are supported for your account type ### Connected but some tools are missing - Account or regional restrictions: certain markets or features may be limited by account level or region - Scope changes: if tool capabilities have been updated, re-authorize to receive the new scopes ### Permission denied on trading actions - Verify trading permissions and market eligibility on your account - Confirm that the current MCP session's OAuth scopes include trading-related permissions ## Llm # LLMs Components We provide several components for LLMs (Large Language Models) that allow you to easily access and analyze financial data, [real-time market data](https://longbridge.com/markets), and even enable AI to place orders.