{"id":51073703,"url":"https://github.com/pooh555/webull-api","last_synced_at":"2026-06-24T13:00:32.156Z","repository":{"id":366429756,"uuid":"1272341744","full_name":"Pooh555/Webull-API","owner":"Pooh555","description":"A C++ SDK for Webull OpenAPI","archived":false,"fork":false,"pushed_at":"2026-06-23T09:22:14.000Z","size":121513,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-23T12:58:05.581Z","etag":null,"topics":["cpp","cpp-library","trading-deployment-kit","webull","webull-api"],"latest_commit_sha":null,"homepage":"https://github.com/Pooh555/Webull-SDK-CPP","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Pooh555.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-17T14:14:09.000Z","updated_at":"2026-06-23T09:22:41.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Pooh555/Webull-API","commit_stats":null,"previous_names":["pooh555/webull-sdk-cpp","pooh555/webull-sdk","pooh555/webull-api"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Pooh555/Webull-API","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pooh555%2FWebull-API","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pooh555%2FWebull-API/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pooh555%2FWebull-API/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pooh555%2FWebull-API/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Pooh555","download_url":"https://codeload.github.com/Pooh555/Webull-API/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pooh555%2FWebull-API/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34733256,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-24T02:00:07.484Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp","cpp-library","trading-deployment-kit","webull","webull-api"],"created_at":"2026-06-23T12:33:49.242Z","updated_at":"2026-06-24T13:00:32.151Z","avatar_url":"https://github.com/Pooh555.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# WDK — Webull Developer Kit\n\n### A Modern C++23 Client for the Webull OpenAPI\n\n**Asynchronous · Thread-Safe · Header-Light · Cryptographically Signed**\n\nBuilt on `libcurl` · `nlohmann/json` · `OpenSSL` · `spdlog`\n\n[![C++](https://img.shields.io/badge/C%2B%2B-23-00599C?style=flat-square\u0026logo=c%2B%2B)](https://en.cppreference.com/w/cpp/23)\n[![Build](https://img.shields.io/badge/build-CMake%20%2B%20Ninja-064F8C?style=flat-square\u0026logo=cmake)](https://cmake.org/)\n[![License](https://img.shields.io/badge/license-MIT-green?style=flat-square)](#license)\n\n\u003c/div\u003e\n\n---\n\n## Overview\nWDK (**Webull Developer Kit**) is a native C++23 client library for the Webull OpenAPI. It provides fully typed, asynchronous access to market data and trading operations through a three-layer architecture that separates transport, signing, and business logic.\n\nThe library was designed with the following principles:\n\n- **Zero dynamic dispatch in the hot path.** All client objects are instantiated by the caller; no virtual tables are used in the core I/O path.\n- **Cooperative ownership.** All heavyweight resources (`CurlPool`, `ThreadPool`, `Token`) are managed through `std::unique_ptr` by the consuming application. Clients receive non-owning references.\n- **Symmetric async/sync surface.** Every client method has both a blocking synchronous variant and a `std::future`-returning asynchronous variant. The caller selects the scheduling model.\n- **Request signing encapsulated from business logic.** HMAC-SHA1 signing, nonce generation, and UTC timestamping are performed inside `wdk::utilities::execute_request` and are never visible to the calling code.\n\n## Documentation\nVisit the full documentation here: [Documentation](docs/documentation.md)\n\nVisit the documentation for LLMs here: [Documentation for AI Agents](docs/llms.txt)\n\n## Prerequisites\n\n### Compiler\n\n| Requirement | Minimum Version |\n|---|---|\n| GCC | 13.0 |\n| Clang | 17.0 |\n| C++ Standard | C++23 (`-std=c++23`) |\n\n### Build Tools\n\n| Tool | Purpose |\n|---|---|\n| CMake | Build system generator |\n| Ninja | Recommended build backend |\n\n### Runtime Dependencies\n\n| Library | Purpose | Notes |\n|---|---|---|\n| `libcurl` | HTTP transport | With HTTPS / HTTP/2 support |\n| `OpenSSL` | HMAC-SHA1, MD5, Base64 | libcrypto is used |\n| `spdlog` | Structured logging | Header-only mode supported |\n| `nlohmann/json` | JSON serialization | Bundled under `lib/` |\n\nAll dependencies except `nlohmann/json` must be installed system-wide and discoverable by CMake's `find_package`.\n\nOn a Debian/Ubuntu system:\n\n```sh\nsudo apt install libcurl4-openssl-dev libssl-dev libspdlog-dev cmake ninja-build\n```\n\nOn Arch Linux:\n\n```sh\nsudo pacman -S curl openssl spdlog cmake ninja\n```\n\n\n## Installation\n### Quick Start\nCloning the main repository.\n### Building from Source\n\nClone the repository and use the provided build script:\n\n```sh\ngit clone https://github.com/Pooh555/Webull-SDK.git\ncd Webull-SDK\n./build.sh\n```\n\nThe build script accepts the following flags:\n\n| Flag | Description | Default |\n|---|---|---|\n| `-b, --build-type \u003ctype\u003e` | CMake build type: `Debug`, `Release`, `RelWithDebInfo` | `Debug` |\n| `-c, --clean` | Remove the existing build directory before building | Off |\n| `-h, --help` | Print the help menu and exit | — |\n\n**Example: release build**\n\n```sh\n./build.sh --build-type Release\n```\n\n**Example: clean debug build**\n\n```sh\n./build.sh --clean\n```\n\nUpon successful completion, the following artifacts are produced:\n\n| Artifact | Location |\n|---|---|\n| Static library | `out/build/\u003cpreset\u003e/libWebull-SDK.a` |\n| Demo binary | `examples/bin/Webull-SDK-Demo` |\n\nTo execute the bundled demo:\n\n```sh\n./run.sh\n```\n\n### Integration as a Third-Party Library\n\nWDK exposes a CMake target `Webull::SDK` for downstream consumption.\n\n**Step 1.** Add the repository as a Git submodule:\n\n```sh\ngit submodule add https://github.com/Pooh555/Webull-SDK.git third-party/Webull-SDK\ngit submodule update --init --recursive\n```\n\n**Step 2.** Configure your project's `CMakeLists.txt`:\n\n```cmake\nadd_subdirectory(third-party/Webull-SDK)\n\nadd_executable(MyApplication\n    src/main.cpp\n)\n\ntarget_link_libraries(MyApplication\n    PRIVATE\n        Webull::SDK\n)\n```\n\n**Step 3.** Call `cmake --build` as usual. The `Webull::SDK` target propagates all required include directories and compile options transitively.\n\n## Usage Guide\n\n### Initialization\n\nThe following objects must be constructed before any client can be used. They are typically held by the application's top-level class.\n\n```cpp\n#include \u003ccore/credentials.hpp\u003e\n#include \u003ccore/curl_pool.hpp\u003e\n#include \u003ccore/thread_pool.hpp\u003e\n#include \u003ccore/token.hpp\u003e\n\nstatic constexpr std::string_view HOST             { \"api.webull.co.th\" };\nstatic constexpr std::string_view TOKEN_PATH       { \"examples/res/token.json\" };\nstatic constexpr std::string_view CREDENTIALS_PATH { \"examples/res/credentials.json\" };\n\n// Allocate infrastructure (order matters: pool and credentials before token)\nauto curl_pool   = std::make_unique\u003cwdk::core::CurlPool\u003e(10uz);\nauto thread_pool = std::make_unique\u003cwdk::core::ThreadPool\u003e();\nauto credentials = std::make_unique\u003cwdk::core::Credentials\u003e(CREDENTIALS_PATH);\n\n// Token constructor blocks until the session is active.\n// The user may need to approve the login in the Webull mobile app.\nauto token = std::make_unique\u003cwdk::core::Token\u003e(\n    TOKEN_PATH, *curl_pool, *credentials, HOST\n);\n```\n\n### Market Data\n\n#### Tick Data\n\n```cpp\nwdk::client::MarketClient market_client(\n    *curl_pool, *thread_pool, *credentials, HOST, token-\u003eget_handle()\n);\n```cpp\nstd::future\u003cwdk::utilities::Response\u003e future = market_client.fetch_historical_bars_data_async({\n    .symbol               { \"AAPL\" },\n    .category             { \"US_STOCK\" },\n    .timespan             { \"M5\" },\n    .count                { 100uz },\n    .real_time_required   { false },\n    .trading_sessions     { \"CORE\" }\n});\n\nwdk::utilities::Response response = future.get();\n\nif (response.http_code == 200L) {\n    std::vector\u003cwdk::data::HistoricalBarsData\u003e history =\n        wdk::data::convert_response_to_historical_bars_vector(response);\n\n    for (const auto\u0026 symbol_data : history) {\n        for (const auto\u0026 bar : symbol_data.bars) {\n            // Access bar.time, bar.open, bar.high, bar.low, bar.close, bar.volume\n        }\n    }\n}\n```\n### Trading Operations\n\n\u003e Before placing orders, always call `preview_order` first to validate the request and review estimated costs.\n\n#### Order Lifecycle Example\n\n```cpp\nwdk::client::TradingClient trading_client(\n    *curl_pool, *thread_pool, *credentials, HOST, token-\u003eget_handle()\n);\n\nconst std::string account_id      = trading_client.get_account_id();\nconst std::string client_order_id = wdk::utilities::generate_nonce();\n\n// Step 1: Preview the order\nwdk::utilities::Response preview = trading_client.preview_order({\n    .account_id      { account_id },\n    .combo_type      { \"NORMAL\" },\n    .client_order_id { client_order_id },\n    .instrument_type { \"EQUITY\" },\n    .market          { \"US\" },\n    .symbol          { \"NVDA\" },\n    .order_type      { \"LIMIT\" },\n    .entrust_type    { \"QTY\" },\n    .trading_session { \"CORE\" },\n    .time_in_force   { \"DAY\" },\n    .side            { \"BUY\" },\n    .quantity        { 1.0 },\n    .limit_price     { 135.00 },\n    .stop_price      { std::nullopt }\n});\n\n// Step 2: Place the order (only if preview confirms acceptable terms)\nif (preview.http_code == 200L) {\n    wdk::utilities::Response placed = trading_client.place_order({\n        .account_id      { account_id },\n        .combo_type      { \"NORMAL\" },\n        .client_order_id { client_order_id },\n        .instrument_type { \"EQUITY\" },\n        .market          { \"US\" },\n        .symbol          { \"NVDA\" },\n        .order_type      { \"LIMIT\" },\n        .entrust_type    { \"QTY\" },\n        .trading_session { \"CORE\" },\n        .time_in_force   { \"DAY\" },\n        .side            { \"BUY\" },\n        .quantity        { 1.0 },\n        .limit_price     { 135.00 },\n        .stop_price      { std::nullopt }\n    });\n}\n\n// Step 3: Modify the order price\nwdk::utilities::Response modified = trading_client.modify_order({\n    .account_id      { account_id },\n    .client_order_id { client_order_id },\n    .time_in_force   { \"DAY\" },\n    .quantity        { 1.0 },\n    .limit_price     { 134.50 },\n    .stop_price      { std::nullopt }\n});\n\n// Step 4: Cancel the order\nwdk::utilities::Response cancelled = trading_client.cancel_order({\n    .account_id      { account_id },\n    .client_order_id { client_order_id }\n});\n```\n\n---\n\n### Account Management\n\n```cpp\n// Fetch account list (and resolve the primary account ID in one call)\nconst std::string account_id = trading_client.get_account_id();\n\n// Account balance\nstd::future\u003cwdk::utilities::Response\u003e balance_future =\n    trading_client.fetch_account_balance_async(account_id);\nwdk::utilities::Response balance = balance_future.get();\n\n// Open positions\nstd::future\u003cwdk::utilities::Response\u003e position_future =\n    trading_client.fetch_account_position_async(account_id);\nwdk::utilities::Response positions = position_future.get();\n\n// Order history (paginated)\nstd::future\u003cwdk::utilities::Response\u003e history_future =\n    trading_client.fetch_order_history_async({\n        .account_id     { account_id },\n        .start_date     { \"2026-01-01\" },\n        .page_size      { 50uz },\n        .last_client_id { \"\" }\n    });\nwdk::utilities::Response history = history_future.get();\n```\n---\n\n\u003cdiv align=\"center\"\u003e\n\n_Given Python's dubious appeal and the questionable maintenance of the Java SDK, C++ was an inevitability._\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpooh555%2Fwebull-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpooh555%2Fwebull-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpooh555%2Fwebull-api/lists"}