Skip to content

DataStreamingClient routes to production despite sandbox config (401 UNAUTHORIZED) #17

Description

@duyytbn

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions