Which Webull this package is talking to — production, or the UAT environment.
This venue's demo story is only half a story, and that half matters
Gemini's demo environment is a complete parallel exchange: REST and streaming both. This one is not.
| Production | UAT | |
|---|---|---|
| REST | api.webull.com | us-openapi-alb.uat.webullbroker.com |
| Streaming | wss://data-api.webull.com:8883/mqtt | none |
The prior adapter records the measurement that establishes it:
mqtt-uat.webullbroker.com → NXDOMAIN. There is no UAT broker to connect to, and no
amount of configuration produces one.
So environment: :uat gives a consumer authenticated REST against test data and no
live stream at all. That is a genuinely useful thing — order placement and account
calls can be exercised without money — and it is also a trap if a package pretends
otherwise. subscribe/2 in UAT does not silently fall back to production, because a
consumer testing against UAT who received production prices would be reading real
market data while believing it was fake. It refuses.
streaming?/1 exists so a caller can ask before it commits, rather than discovering
the gap from a subscription that never delivers.
Resolution order
- an explicit
:environmentin the call's options — wins always DpExchange.Core.Config, which resolves per process, so one async test or one strategy runner can sit in UAT while its neighbours do not:production
Production is the default and an unrecognised value raises. A typo must not quietly resolve to production: the failure is asymmetric, since meaning UAT and getting production sends a real order to a real broker.
Summary
Functions
REST hostname without a scheme.
Every environment this package knows.
Whether this environment moves real money.
The environment in force for these options.
REST base URL, with scheme.
Whether this environment has a live stream at all.
The MQTT-over-WebSocket URL, or nil where the venue offers none.
Types
Functions
REST hostname without a scheme.
Separate from rest_url/1 because the host participates in the signature — Webull
signs it so a signature cannot be replayed against another environment. A caller needs
both, and they must agree.
@spec known() :: [t()]
Every environment this package knows.
Whether this environment moves real money.
The environment in force for these options.
REST base URL, with scheme.
Whether this environment has a live stream at all.
Asked before subscribing, so a consumer learns the answer from a question rather than from a subscription that never delivers.
The MQTT-over-WebSocket URL, or nil where the venue offers none.
nil is the honest answer for UAT and is not a configuration gap to fill in.