Orders
Webull provides a Trading API that allows developers to trade and query through the HTTP protocol.
For more details, please refer to the API Reference.
Before calling the Trading API, you need to have an App Key and App Secret.
Note
Due to security and compliance requirements in Hong Kong, OpenAPI requires not only identity verification with App Key and secret signature, but also an additional Token verification.
For token creation and verification, please refer to Token Creation and Verification.
1. Supported Markets
The Trading API supports the following markets:
| Market | Products |
|---|---|
| United States | US equity products (stocks, options—excluding index options) |
| Hong Kong | Hong Kong equity products (including stocks, ETFs) |
| Mainland China | Stock Connect stocks |
2. Base URLs
- Production Environment:
https://api.webull.hk/ - Sandbox Environment:
https://api.sandbox.webull.hk
3. Code Example
3.1 Stock Orders
- Python
- Java
import uuid
from webull.core.client import ApiClient
from webull.trade.trade_client import TradeClient
optional_api_endpoint = "<webull_api_host>" # PRD env host: api.webull.hk. Test env host: api.sanbox.webull.hk
your_app_key = "<your_app_key>"
your_app_secret = "<your_app_secret>"
region_id = "hk"
account_id = "<your_account_id>" # Use account_list interface to get account info
api_client = ApiClient(your_app_key, your_app_secret, region_id)
api_client.add_endpoint(region_id, optional_api_endpoint)
if __name__ == '__main__':
trade_client = TradeClient(api_client)
# simple order
client_order_id = uuid.uuid4().hex
print('client order id:', client_order_id)
new_simple_orders = [
{
"client_order_id": client_order_id,
"symbol": "BULL",
"instrument_type": "EQUITY",
"market": "US",
"order_type": "LIMIT",
"limit_price": "26",
"quantity": "1",
"support_trading_session": "CORE",
"side": "BUY",
"time_in_force": "DAY",
"entrust_type": "QTY"
}
]
# For hk stock place params
new_hk_stock_simple_orders = [
{
"client_order_id": client_order_id,
"symbol": "00700",
"instrument_type": "EQUITY",
"market": "HK",
"order_type": "ENHANCED_LIMIT",
"limit_price": "612",
"quantity": "100",
"side": "BUY",
"time_in_force": "DAY",
"entrust_type": "QTY"
}
]
res = trade_client.order_v2.preview_order(account_id, new_simple_orders)
if res.status_code == 200:
print('preview order res:', res.json())
res = trade_client.order_v2.place_order(account_id, new_simple_orders)
if res.status_code == 200:
print('place order res:', res.json())
modify_simple_orders = [
{
"client_order_id": client_order_id,
"quantity": "2",
"limit_price": "25"
}
]
res = trade_client.order_v2.replace_order(account_id, modify_simple_orders)
if res.status_code == 200:
print('replace order res:', res.json())
res = trade_client.order_v2.cancel_order(account_id, client_order_id)
if res.status_code == 200:
print('cancel order res:', res.json())
res = trade_client.order_v2.get_order_detail(account_id, client_order_id)
if res.status_code == 200:
print('order detail:', res.json())
import com.webull.openapi.core.common.Region;
import com.webull.openapi.core.common.dict.*;
import com.webull.openapi.core.http.HttpApiConfig;
import com.webull.openapi.core.logger.Logger;
import com.webull.openapi.core.logger.LoggerFactory;
import com.webull.openapi.core.utils.GUID;
import com.webull.openapi.samples.config.Env;
import com.webull.openapi.trade.request.v2.TradeOrder;
import com.webull.openapi.trade.request.v2.TradeOrderItem;
import com.webull.openapi.trade.response.v2.OrderHistory;
import com.webull.openapi.trade.response.v2.TradeOrderResponse;
import java.util.ArrayList;
import java.util.List;
public class OrderStockTradeClient {
private static final Logger logger = LoggerFactory.getLogger(OrderStockTradeClient.class);
public static void main(String[] args) {
OrderStockTradeClient orderStockTradeClient = new OrderStockTradeClient();
HttpApiConfig apiConfig = HttpApiConfig.builder()
.appKey("<your_app_key>") //<your_app_key>
.appSecret("<your_app_secret>") //<your_app_secret>
.regionId("hk") //<your_region_id> @see com.webull.openapi.core.common.Region
.endpoint("<webull_api_host>") //PRD env host: api.webull.hk. Test env host: api.sanbox.webull.hk
.build();
com.webull.openapi.trade.TradeClientV2 apiService = new com.webull.openapi.trade.TradeClientV2(apiConfig);
// Use getAccountList interface to get account info
String accountId = "#{accountId}"; //<your_account_id> from by Account Api
String clientOrderId = GUID.get();
com.webull.openapi.trade.TradeClientV2 apiService = new com.webull.openapi.trade.TradeClientV2(apiConfig);
// build place order params
TradeOrder tradeOrder = orderStockTradeClient.buildPlaceStockParams(clientOrderId);
// place order
TradeOrderResponse placeOrderResp = apiService.placeOrder(accountId,tradeOrder);
logger.info("Place order response: {}", placeOrderResp);
// get order detail
OrderHistory orderDetail = apiService.getOrderDetails(accountId,clientOrderId);
logger.info("Order details response: {}", orderDetail);
// replace order
TradeOrder modifyTradeOrder = orderStockTradeClient.buildReplaceOrderParams(clientOrderId);
TradeOrderResponse modifyOrderResponse = apiService.replaceOrder(accountId, modifyTradeOrder);
logger.info("Order modify response: {}", modifyOrderResponse);
// query order detail after replace order
OrderHistory orderDetail1 = apiService.getOrderDetails(accountId, clientOrderId);
logger.info("Order orderDetail response after replace order: {}", orderDetail1);
// cancel order
TradeOrder cancelOrder = new TradeOrder();
cancelOrder.setClientOrderId(clientOrderId);
TradeOrderResponse cancelOrderResponse = apiService.cancelOrder(accountId, cancelOrder);
logger.info("Order cancel order response: {}", cancelOrderResponse);
// query order detail after cancel order
OrderHistory orderDetail2 = apiService.getOrderDetails(accountId, clientOrderId);
logger.info("Order orderDetail response after cancel: {}", orderDetail2.getOrders().get(0).getStatus());
}
/**
* build hk stock place params
* Only for Webull HK's Client
* @param clientOrderId
* @return
*/
private TradeOrder buildPlaceHKStockParams(String clientOrderId) {
TradeOrder tradeOrder = new TradeOrder();
List<TradeOrderItem> newOrders = new ArrayList<>();
TradeOrderItem placeOne = new TradeOrderItem();
placeOne.setClientOrderId(clientOrderId);
// WebullUS need set combo_type, because WebullUS support combo order
placeOne.setComboType(ComboType.NORMAL.name());
newOrders.add(placeOne);
placeOne.setSymbol("00700");
placeOne.setInstrumentType(InstrumentSuperType.EQUITY.name());
placeOne.setMarket("HK");
placeOne.setOrderType(OrderType.ENHANCED_LIMIT.name());
placeOne.setQuantity("100");
placeOne.setLimitPrice("610");
placeOne.setSide(OrderSide.BUY.name());
placeOne.setTimeInForce(OrderTIF.DAY.name());
placeOne.setEntrustType(EntrustType.QTY.name());
tradeOrder.setNewOrders(newOrders);
return tradeOrder;
}
/**
* build your place order object
*
* @param clientOrderId
* @return
*/
private TradeOrder buildPlaceStockParams(String clientOrderId) {
TradeOrder tradeOrder = new TradeOrder();
List<TradeOrderItem> newOrders = new ArrayList<>();
TradeOrderItem placeOne = new TradeOrderItem();
placeOne.setClientOrderId(clientOrderId);
// WebullUS need set combo_type, because WebullUS support combo order
placeOne.setComboType(ComboType.NORMAL.name());
newOrders.add(placeOne);
placeOne.setSymbol("BULL");
placeOne.setInstrumentType(InstrumentSuperType.EQUITY.name());
placeOne.setMarket(Region.us.name().toUpperCase());
placeOne.setOrderType(OrderType.LIMIT.name());
placeOne.setQuantity("1");
placeOne.setLimitPrice("25");
placeOne.setSupportTradingSession("ALL");
placeOne.setSide(OrderSide.BUY.name());
placeOne.setTimeInForce(OrderTIF.DAY.name());
placeOne.setEntrustType(EntrustType.QTY.name());
tradeOrder.setNewOrders(newOrders);
return tradeOrder;
}
/**
* build your replace order params
* @param clientOrderId
* @return replace order object
*/
private TradeOrder buildReplaceOrderParams(String clientOrderId) {
TradeOrder replaceTradeOrder = new TradeOrder();
List<TradeOrderItem> modifyOrders = new ArrayList<>();
TradeOrderItem modifyOne = new TradeOrderItem();
modifyOne.setClientOrderId(clientOrderId);
modifyOne.setLimitPrice("25");
modifyOne.setQuantity("2");
modifyOrders.add(modifyOne);
replaceTradeOrder.setModifyOrders(modifyOrders);
return replaceTradeOrder;
}
}
3.2 Option Orders
- Python
- Java
import uuid
from webull.core.client import ApiClient
from webull.trade.trade_client import TradeClient
optional_api_endpoint = "<webull_api_host>" # PRD env host: api.webull.hk. Test env host: api.sanbox.webull.hk
your_app_key = "<your_app_key>"
your_app_secret = "<your_app_secret>"
region_id = "hk"
account_id = "<your_account_id>" # Use account_list interface to get account info
api_client = ApiClient(your_app_key, your_app_secret, region_id)
api_client.add_endpoint(region_id, optional_api_endpoint)
if __name__ == '__main__':
trade_client = TradeClient(api_client)
# simple order
client_order_id = uuid.uuid4().hex
print('client order id:', client_order_id)
new_simple_orders = [
{
"client_order_id": client_order_id,
"symbol": "BULL",
"instrument_type": "EQUITY",
"market": "US",
"order_type": "LIMIT",
"limit_price": "26",
"quantity": "1",
"support_trading_session": "CORE",
"side": "BUY",
"time_in_force": "DAY",
"entrust_type": "QTY"
}
]
res = trade_client.order_v2.preview_order(account_id, new_simple_orders)
if res.status_code == 200:
print('preview order res:', res.json())
res = trade_client.order_v2.place_order(account_id, new_simple_orders)
if res.status_code == 200:
print('place order res:', res.json())
modify_simple_orders = [
{
"client_order_id": client_order_id,
"quantity": "2",
"limit_price": "25"
}
]
res = trade_client.order_v2.replace_order(account_id, modify_simple_orders)
if res.status_code == 200:
print('replace order res:', res.json())
res = trade_client.order_v2.cancel_order(account_id, client_order_id)
if res.status_code == 200:
print('cancel order res:', res.json())
res = trade_client.order_v2.get_order_detail(account_id, client_order_id)
if res.status_code == 200:
print('order detail:', res.json())
import com.webull.openapi.core.common.dict.*;
import com.webull.openapi.core.http.HttpApiConfig;
import com.webull.openapi.core.logger.Logger;
import com.webull.openapi.core.logger.LoggerFactory;
import com.webull.openapi.core.utils.GUID;
import com.webull.openapi.trade.request.v2.OptionOrder;
import com.webull.openapi.trade.request.v2.OptionOrderItem;
import com.webull.openapi.trade.request.v2.OptionOrderItemLeg;
import com.webull.openapi.trade.response.v2.OrderHistory;
import com.webull.openapi.trade.response.v2.TradeOrderResponse;
import java.util.ArrayList;
import java.util.List;
public class OrderOptionTradeClient {
private static final Logger logger = LoggerFactory.getLogger(OrderOptionTradeClient.class);
public static void main(String[] args) {
OrderOptionTradeClient orderOptionTradeClient = new OrderOptionTradeClient();
HttpApiConfig apiConfig = HttpApiConfig.builder()
.appKey("<your_app_key>") //<your_app_key>
.appSecret("<your_app_secret>") //<your_app_secret>
.regionId("hk") //<your_region_id> @see com.webull.openapi.core.common.Region
.endpoint("<webull_api_host>") //PRD env host: api.webull.hk. Test env host: api.sanbox.webull.hk
.build();
com.webull.openapi.trade.TradeClientV2 apiService = new com.webull.openapi.trade.TradeClientV2(apiConfig);
// Use getAccountList interface to get account info
String accountId = "#{accountId}"; //<your_account_id> from by Account Api
String clientOrderId = GUID.get();
// build place option order params
OptionOrder optionOrder = orderOptionTradeClient.buildOptionPlaceParams(clientOrderId);
TradeOrderResponse tradeOrderResponse = apiService.placeOption(accountId, optionOrder);
logger.info("Place option order response: {}", tradeOrderResponse);
// get option order detail
OrderHistory orderDetails = apiService.getOrderDetails(accountId, clientOrderId);
logger.info("Order details response: {}", orderDetails);
OptionOrder replaceOptionOrder = orderOptionTradeClient.buildReplaceOptionPlaceParams(clientOrderId);
TradeOrderResponse replaceResponse = apiService.replaceOption(accountId, replaceOptionOrder);
logger.info("Replace option order response: {}", replaceResponse);
// get option order detail
OrderHistory orderDetails2= apiService.getOrderDetails(accountId, clientOrderId);
logger.info("Order details response: {}", orderDetails2);
// cancel order
OptionOrder cancelOption = new OptionOrder();
cancelOption.setClientOr derId(clientOrderId);
TradeOrderResponse orderResponse = apiService.cancelOption(accountId, cancelOption);
logger.info("Option order cancel response: {}", orderResponse);
}
/**
* build your option stock place params
* @param clientOrderId
* @return option order place params
*/
private OptionOrder buildOptionPlaceParams(String clientOrderId) {
// Options
OptionOrderItemLeg optionOrderItemLeg = new OptionOrderItemLeg();
optionOrderItemLeg.setSide(OrderSide.BUY.name());
optionOrderItemLeg.setQuantity("1");
optionOrderItemLeg.setSymbol("AAPL");
optionOrderItemLeg.setStrikePrice("251");
optionOrderItemLeg.setOptionExpireDate("2025-11-19");
optionOrderItemLeg.setInstrumentType(InstrumentSuperType.OPTION.name());
optionOrderItemLeg.setOptionType(OptionType.CALL.name());
optionOrderItemLeg.setMarket(Markets.US.name());
List<OptionOrderItemLeg> optionOrderItemLegList = new ArrayList<>();
optionOrderItemLegList.add(optionOrderItemLeg);
OptionOrderItem optionOrderItem = new OptionOrderItem();
optionOrderItem.setClientOrderId(clientOrderId);
optionOrderItem.setComboType(ComboType.NORMAL.name());
optionOrderItem.setOptionStrategy(OptionStrategy.SINGLE.name());
optionOrderItem.setSide(OrderSide.BUY.name());
optionOrderItem.setOrderType(OrderType.LIMIT.name());
optionOrderItem.setTimeInForce(OrderTIF.GTC.name());
optionOrderItem.setLimitPrice("20.5");
optionOrderItem.setQuantity("1");
optionOrderItem.setEntrustType(EntrustType.QTY.name());
optionOrderItem.setLegs(optionOrderItemLegList);
List<OptionOrderItem> optionOrderItemList = new ArrayList<>();
optionOrderItemList.add(optionOrderItem);
OptionOrder optionOrder = new OptionOrder();
optionOrder.setNewOrders(optionOrderItemList);
return optionOrder;
}
/**
* build your option stock place params
* @param clientOrderId
* @return option order place params
*/
private OptionOrder buildReplaceOptionPlaceParams(String clientOrderId) {
OptionOrder replaceOptionOrder = new OptionOrder();
replaceOptionOrder.setClientOrderId(clientOrderId);
List<OptionOrderItem> modifyOrders = new ArrayList<>();
replaceOptionOrder.setModifyOrders(modifyOrders);
OptionOrderItem optionOrderItem = new OptionOrderItem();
modifyOrders.add(optionOrderItem);
optionOrderItem.setClientOrderId(clientOrderId);
optionOrderItem.setQuantity("2");
return replaceOptionOrder;
}
}