Getting Started
A quick guide to get you from zero to your first market data request. We'll install the SDK, set up authentication, and run two examples: fetching historical bars and subscribing to real-time quotes.
Prerequisites
- Python 3.8–3.14 or Java JDK 8+
- App Key and App Secret. See Individual Application Process or use the shared test accounts.
Accessing market data (both historical and real-time) for US stocks and ETFs requires an active OpenAPI market data subscription. If you receive a 403 error when running the examples below, you likely need to subscribe first. See Subscribe Advanced Quotes for details.
Step 1: Install the SDK
- Python
- Java
pip3 install --upgrade webull-openapi-python-sdk
<dependency>
<groupId>com.webull.openapi</groupId>
<artifactId>webull-openapi-java-sdk</artifactId>
<version>1.0.3</version>
</dependency>
Step 2: Fetch Historical Data
This example retrieves 1-minute candlestick bars for AAPL:
from webull.data.common.category import Category
from webull.data.common.timespan import Timespan
from webull.core.client import ApiClient
from webull.data.data_client import DataClient
api_client = ApiClient("<your_app_key>", "<your_app_secret>", "us")
api_client.add_endpoint("us", "<api_endpoint>")
data_client = DataClient(api_client)
# Single symbol
res = data_client.market_data.get_history_bar("AAPL", Category.US_STOCK.name, Timespan.M1.name)
if res.status_code == 200:
print("History bar:", res.json())
# Batch query (multiple symbols)
res = data_client.market_data.get_batch_history_bar(
["AAPL", "TSLA"], Category.US_STOCK.name, Timespan.M1.name, 1
)
if res.status_code == 200:
print("Batch history bar:", res.json())
- Production:
api.webull.com - Test:
api.sandbox.webull.com
Step 3: Subscribe to Real-Time Quotes
This example connects to the MQTT streaming service and subscribes to real-time quote, snapshot, and tick data for AAPL:
from webull.data.common.category import Category
from webull.data.common.subscribe_type import SubscribeType
from webull.data.data_streaming_client import DataStreamingClient
data_streaming_client = DataStreamingClient(
"<your_app_key>",
"<your_app_secret>",
"us",
"demo_session_1",
http_host="<api_endpoint>",
mqtt_host="<data_api_endpoint>",
)
def on_connect(client, api_client, session_id):
print("Connected:", client.get_session_id())
client.subscribe(
["AAPL"],
Category.US_STOCK.name,
[SubscribeType.QUOTE.name, SubscribeType.SNAPSHOT.name, SubscribeType.TICK.name],
)
def on_message(client, topic, quotes):
print("Topic:", topic, "Data:", quotes)
def on_subscribe(client, api_client, session_id):
print("Subscribed:", client.get_session_id())
data_streaming_client.on_connect_success = on_connect
data_streaming_client.on_quotes_message = on_message
data_streaming_client.on_subscribe_success = on_subscribe
data_streaming_client.connect_and_loop_forever()
For US server-to-server integrations:
| Environment | HTTP host for subscribe/unsubscribe | MQTT endpoint |
|---|---|---|
| Production | api.webull.com | data-api.webull.com:1883 |
| Test | api.sandbox.webull.com | data-api.sandbox.webull.com:1883 |
The HTTP host and MQTT broker are intentionally different. Pass the HTTP host as http_host, the MQTT hostname as mqtt_host, and use the same session_id for the subscribe request and MQTT ClientId. The official SDK uses TCP port 1883 with TLS enabled by default.
If you prefer not to use the SDK for streaming, see Data Streaming API for the raw MQTT integration guide.
What's Next
- Data API — HTTP endpoints for historical and snapshot data
- Data Streaming API — MQTT protocol details for real-time streaming
- Market Data API Overview — Full list of available endpoints and rate limits