SUBJECT: DataStreamingClient consistently routes to production (api.webull.com)
despite explicit sandbox configuration, causing 401 UNAUTHORIZED with
test/sandbox credentials
Sorry my english is not good, I am using Claude to write this.
ENVIRONMENT:
- webull-openapi-python-sdk version 2.0.18 (Core 2.0.18)
- Python 3.12.7, Windows 11
- Confirmed reproducible identically across 3 consecutive runs after
switching from Python 3.14 to 3.12 (3.14 caused non-deterministic
behavior — different errors on identical code, likely a threading
compatibility issue, since 3.14 is outside the SDK's documented
3.8-3.13 support range)
WHAT WORKS:
The documented pattern for TradeClient correctly routes to sandbox:
api_client = ApiClient(app_key, app_secret, "us")
api_client.add_endpoint("us", "api.sandbox.webull.com")
trade_client = TradeClient(api_client)
This successfully authenticates and returns account list, balance, and
positions against the sandbox environment.
WHAT FAILS:
DataStreamingClient, configured with the documented http_host/mqtt_host
constructor arguments AND an explicit add_endpoint call on its internal
api_client, still routes the initial /openapi/config check to production
(api.webull.com), which correctly rejects our sandbox-scoped credentials
with a 401.
Code:
client = DataStreamingClient(
app_key, app_secret, "us", uuid.uuid4().hex,
http_host="api.sandbox.webull.com",
mqtt_host="data-api.sandbox.webull.com",
)
client.api_client.add_endpoint("us", "api.sandbox.webull.com")
client.connect_and_loop_forever() # run in a background thread
Resulting error (100% reproducible across repeated runs on Python 3.12):
ServerException occurred. Host:api.webull.com ...
Response: {'message': 'Invalid credentials. Please verify your
credentials and ensure you are connecting to the correct
environment', 'error_code': 'UNAUTHORIZED'}
HTTP Status: 401, Code: UNAUTHORIZED
QUESTION FOR WEBULL:
Is there a different, correct way to configure DataStreamingClient for
the sandbox/test environment specifically? The http_host/mqtt_host
constructor kwargs and the add_endpoint() call (which both work
correctly for TradeClient/ApiClient) don't appear to affect the internal
/openapi/config check that DataStreamingClient performs during
connect_and_loop_forever().
Also relevant: we separately observed an "rc code: 101, msg: Internal
error" during the MQTT CONNACK phase in earlier testing (before pinning
down the Python version issue), which may or may not be related.
SUBJECT: DataStreamingClient consistently routes to production (api.webull.com)
despite explicit sandbox configuration, causing 401 UNAUTHORIZED with
test/sandbox credentials
Sorry my english is not good, I am using Claude to write this.
ENVIRONMENT:
switching from Python 3.14 to 3.12 (3.14 caused non-deterministic
behavior — different errors on identical code, likely a threading
compatibility issue, since 3.14 is outside the SDK's documented
3.8-3.13 support range)
WHAT WORKS:
The documented pattern for TradeClient correctly routes to sandbox:
api_client = ApiClient(app_key, app_secret, "us")
api_client.add_endpoint("us", "api.sandbox.webull.com")
trade_client = TradeClient(api_client)
This successfully authenticates and returns account list, balance, and
positions against the sandbox environment.
WHAT FAILS:
DataStreamingClient, configured with the documented http_host/mqtt_host
constructor arguments AND an explicit add_endpoint call on its internal
api_client, still routes the initial /openapi/config check to production
(api.webull.com), which correctly rejects our sandbox-scoped credentials
with a 401.
Code:
client = DataStreamingClient(
app_key, app_secret, "us", uuid.uuid4().hex,
http_host="api.sandbox.webull.com",
mqtt_host="data-api.sandbox.webull.com",
)
client.api_client.add_endpoint("us", "api.sandbox.webull.com")
client.connect_and_loop_forever() # run in a background thread
Resulting error (100% reproducible across repeated runs on Python 3.12):
ServerException occurred. Host:api.webull.com ...
Response: {'message': 'Invalid credentials. Please verify your
credentials and ensure you are connecting to the correct
environment', 'error_code': 'UNAUTHORIZED'}
HTTP Status: 401, Code: UNAUTHORIZED
QUESTION FOR WEBULL:
Is there a different, correct way to configure DataStreamingClient for
the sandbox/test environment specifically? The http_host/mqtt_host
constructor kwargs and the add_endpoint() call (which both work
correctly for TradeClient/ApiClient) don't appear to affect the internal
/openapi/config check that DataStreamingClient performs during
connect_and_loop_forever().
Also relevant: we separately observed an "rc code: 101, msg: Internal
error" during the MQTT CONNACK phase in earlier testing (before pinning
down the Python version issue), which may or may not be related.