Streaming & Events
WebSocket clients for market data (stocks, crypto, options, news) and a trading
stream (order/trade updates). Both authenticate automatically, reconnect with
backoff, dispatch their current subscriptions after reconnect authentication,
and ping/pong. The API is a typed Node-style EventEmitter: register listeners,
then connect().
const stocks = alpaca.marketData.stockStream({ feed: "iex" });
stocks.onBar((bar) => console.log(bar));
stocks.onError((msg) => console.error("stream error:", msg));
stocks.onConnect(() => stocks.subscribeForBars(["AAPL", "MSFT"]));
stocks.connect();
const updates = alpaca.trading.stream();
updates.onTradeUpdate((u) => console.log(u.event, u.order.symbol));
updates.subscribeTradeUpdates();
updates.connect();
Set the trading subscription before connect() so the authenticated connection
sends one initial listen frame and reconnects restore the same subscription.
Available streams
All five factories return a stream sharing the lifecycle below:
| Factory | Stream | Data |
|---|---|---|
alpaca.trading.stream() | TradingStream | Order/trade updates (JSON) |
alpaca.marketData.stockStream() | StockDataStream | US-equity bars/trades/quotes (msgpack) |
alpaca.marketData.cryptoStream() | CryptoDataStream | Crypto market data (msgpack) |
alpaca.marketData.optionStream() | OptionDataStream | Options market data (msgpack) |
alpaca.marketData.newsStream() | NewsStream | Real-time news headlines |
Streaming is supported on Node.js and Bun. Edge, browser, and Deno exports are REST-only; see Runtime & module compatibility.
Timestamp precision
Market-data stream events expose two timestamp fields:
timestamp: Date— millisecond precision, convenient for most uses.timestampRaw?: string— the full RFC-3339 nanosecond timestamp, e.g."2024-01-02T03:04:05.678099211Z".
The market-data stream is msgpack, whose default decoder truncates timestamps to
milliseconds. The SDK installs a custom decoder so timestampRaw keeps every
digit Alpaca sends. (This applies to the market-data channels — trades, quotes,
bars, statuses, LULDs, imbalances, corrections, cancel-errors, and orderbooks.)
Trade-id precision
Trade ids are 64-bit integers, which can exceed JavaScript's safe integer range
(2^53). The same custom decoder reads them losslessly, so id-bearing events
expose an exact string alongside the convenient (best-effort) number:
- Trades —
id: numberandidRaw?: string. - Cancel-errors —
id: numberandidRaw?: string. - Corrections —
originalId/correctedId(numbers) andoriginalIdRaw?/correctedIdRaw?(strings). - News —
id: numberandidRaw?: string.
Use idRaw whenever you compare, store, or key on an id; id remains for
display and small values. Other numeric fields (sizes, volumes, counts) stay a
plain number.
The REST canonical trade accessors (getStockTrades/getCryptoTrades) expose
the same idRaw, so ids you backfill over REST match the ones you receive live
— see Trade-id precision in the
market-data guide.
Crypto taker side
Crypto trades carry the aggressor side — who crossed the spread to make the trade happen:
takerSide?: string—"B"(buyer-initiated) or"S"(seller-initiated).
Crypto only: equities trade messages carry no taker side on the wire, so the
field stays undefined there. The REST canonical accessor (getCryptoTrades)
exposes the same field, so taker sides you backfill over REST match the ones
you receive live.
Shared lifecycle
Every stream exposes:
- Lifecycle callbacks —
onConnect(() => …),onDisconnect(() => …),onStateChange((state) => …), andonError((message) => …). State changes expose every transition; a manualdisconnect()emits the disconnect lifecycle exactly once. - Awaitable authentication —
whenAuthenticated()resolves with the stream's eventual typedStreamAuthResult(never rejects);waitForAuthenticationResult(timeoutMs?)also returns a typed result, whilewaitForAuthentication(timeoutMs?)is itsbooleanconvenience wrapper. Failures carry aSTREAM_AUTH_STATUS(server_rejectedwith the servercode,closed,timeout). A caller-side timeout from either wait method does not settle or overwrite the stream's eventual real authentication outcome, sowhenAuthenticated()and other waiters can still receive it. - Reconnect lifecycle —
onReconnecting((attempt) => …)(1-based) andonReconnected(() => …)after re-authentication and re-subscription dispatch, distinct from the firstonConnect. This event does not promise a server subscription acknowledgement. - A custom
urlon any stream to route through a proxy/gateway, plus acallbackExecutorto schedule listener work away from the socket callback. A synchronously throwing listener is isolated and can never break the stream.
const result = await stocks.whenAuthenticated();
if (!result.authenticated) {
console.error(`auth failed: ${result.status} ${result.code ?? ""}`);
}
Connection safety
Lifecycle callbacks, messages, keepalive timers, and reconnect work are scoped
to the socket generation that created them, so a stale socket cannot mutate a
new connection. Ping timers start only after the socket is open. A manual
disconnect() suppresses reconnect and emits the disconnect lifecycle exactly
once.
Malformed frames, decode failures, and event-mapper failures are caught and
reported through onError / CLIENT_ERROR without escaping the socket callback
or crashing the process. The trading protocol's action: "error" frames use
the same error channel. Synchronously throwing listeners are isolated too.
Node's event loop still applies: synchronous listener work blocks other
callbacks and socket processing. Keep listeners short or provide a
callbackExecutor that schedules application work appropriately; callback
isolation prevents failures, not event-loop starvation.
Crypto and news streams have no sandbox endpoint: pass an explicit url to point
them elsewhere, otherwise sandbox: true throws.
stockStream also exposes subscribeForImbalances([...]) / onImbalance(...).
This channel is equities-only and sparse — Alpaca emits imbalance messages mainly
during limit-up/limit-down halts, so long quiet periods are expected even while
subscribed.
Common options
In addition to feed/paper/sandbox: reconnect, maxReconnectAttempts
(UNLIMITED_RECONNECT_ATTEMPTS to retry forever), backoff,
initialReconnectMs, maxReconnectMs, reconnectJitter, pingIntervalMs,
pongWaitMs, url, and callbackExecutor.
For a curated factory and event overview, see the Streaming API Reference; the published TypeScript declarations are the complete surface. For historical/live shape interoperability, see Market Data.