A single Node.js TypeScript SDK for the Alpaca Trading API and Market Data
API. Both APIs live under their own namespace (trading / marketData) in one
package, fronted by a unified Alpaca client with typed errors, resilience
(retry / timeout / rate limiting), pagination helpers, ergonomic order builders,
and real-time streaming.
Upgrading from 3.x? See the Migration guide — it maps every endpoint old → new, explains the ergonomic layer, and ships a codemod that automates most of the work. Both files are included in the published npm package.
- SDK consumers: Node.js >= 20 — the REST transport uses the platform-global
fetch,Headers,URL, andAbortController. (Node 18 reached end-of-life in April 2025; the package declaresengines.node >=20.) - Repository contributors: Node.js >= 24 (see
.nvmrc). Build, docs, generation, and release tooling run on Node 24; CI separately executes the packed SDK on Node 20 to preserve the consumer compatibility floor. - Strict Node TypeScript projects may omit DOM libs; the REST declarations are
portable and do not require
"dom"in the consumertsconfig.
| Runtime | REST | Streaming | Notes |
|---|---|---|---|
| Node.js >= 20 | ✅ | ✅ | Primary target. |
| Bun | ✅ | ✅ | Node-compatible (ws runs). |
| Deno | ✅ | ❌ | Root auto-resolves to the REST build via the deno export condition. |
Cloudflare Workers / workerd |
✅ | ❌ | Root auto-resolves to the REST build (workerd / worker). |
| Vercel Edge | ✅ | ❌ | Root auto-resolves to the REST build (edge-light). |
| Browser | ✅ | ❌ | Resolves to the REST build (browser). Not recommended — see caveat. |
Legend: ✅ supported · ❌ not supported.
- Streaming is Node/Bun only. The WebSocket clients use Node-compatible
streaming modules, which don't run on edge or in the browser. On those
targets the package's
export conditions transparently resolve the root
import to the streaming-free REST build, so REST works
and the stream factories (
stockStream,stream, ...) plussubmitAndWaitthrow if called. For real-time streaming, run on Node or Bun. - Browser: technically works, but discouraged. Calling Alpaca directly from a
browser ships your
APCA_API_SECRET_KEYto the client. Prefer a server or proxy (seeexamples/marketdata-backend.ts) rather than embedding credentials in front-end code.
The same matrix plus the edge-resolution mechanics, module formats, and the REST-only entrypoint are consolidated on the docs site: Runtime & module compatibility.
npm install @alpacahq/alpaca-trade-apiMigrating from 3.x? Follow the
Migration guide.
This README is the canonical, self-contained reference. There is also a
Docusaurus documentation site — curated guides, a
generated API reference, runtime compatibility, and the runnable examples —
hosted at https://alpacahq.github.io/alpaca-trade-api-js/ and deployed
from docs/ on every push to master. You can also read the whole
thing locally in two commands:
npm --prefix docs install # first time only
npm --prefix docs start # dev server → http://localhost:3000/alpaca-trade-api-js/Prefer the exact production build? Run npm --prefix docs run build (which
regenerates the API reference, examples, and migration page first), then
npm --prefix docs run serve. The guides are hand-written under
docs/docs/; the API reference and examples pages are generated
at build time from the SDK's capability maps and examples/; the site migration
page is derived from the canonical MIGRATION.md.
Building on this SDK with an AI coding agent? This repo ships an
Agent Skill that teaches agents the SDK's mental
model, idioms, and where to look. Install it with the open skills CLI — it
auto-detects your agent (Claude Code, Cursor, Codex, …) and installs there:
npx skills add alpacahq/alpaca-trade-api-jsThe skill lives at
skills/alpaca-trade-api-sdk/SKILL.md.
The SDK ships ~16 trading and ~11 market-data Api classes. The Alpaca client
bundles all of them (plus the real-time streams) behind a single constructor:
pass credentials once and reach everything through the .trading and
.marketData namespaces. Sub-APIs are created lazily and memoized.
import { Alpaca } from "@alpacahq/alpaca-trade-api";
const alpaca = new Alpaca({
keyId: process.env.APCA_API_KEY_ID,
secret: process.env.APCA_API_SECRET_KEY,
paper: true, // default; set false for live trading
});
// REST — no manual Configuration / Api wiring
const account = await alpaca.trading.account.getAccount();
const positions = await alpaca.trading.positions.getAllOpenPositions();
// Ergonomic order placement (see "Placing orders")
await alpaca.trading.orders.market({
symbol: "AAPL",
qty: 1,
side: "buy",
clientOrderId: `quickstart-${crypto.randomUUID()}`,
});
// Streaming — shares the same credentials (market data ignores paper/live)
const bars = alpaca.marketData.stockStream({ feed: "iex" });
bars.onBar((b) => console.log(b.symbol, b.close));
bars.onConnect(() => bars.subscribeForBars(["AAPL", "MSFT"]));
bars.connect();The paper flag controls the trading REST host (paper-api vs api) and the
default trading-updates stream endpoint; market data always uses
data.alpaca.markets. The trading / marketData namespaces remain available
if you prefer to construct Api classes yourself:
import { trading, marketData } from "@alpacahq/alpaca-trade-api";
const orders = new trading.OrdersApi(new trading.Configuration({ keyId, secret }));
const stocks = new marketData.StockApi(new marketData.Configuration({ keyId, secret }));The Alpaca client is two layers, and knowing the rule is the whole mental
model:
- Generated (always present, uniform). Every generated REST method is
reachable raw at
alpaca.<group>.<resource>.<method>(...)— e.g.alpaca.trading.assets.getV2Assets()oralpaca.marketData.stocks.stockBars(...). Nothing is ever hidden or removed. - Ergonomic (additive, never replaces layer 1). A curated set of hand-written conveniences sits on top: order builders, normalized market-data accessors, pagination, and workflow helpers. They are additions — the raw method each one builds on is still there.
So the rule you can rely on: if there's no ergonomic helper for what you need, the raw generated method is always available. You never have to guess whether a resource is "ergonomic" or "raw" — it's both.
Three maps make this queryable (each also has a lookup):
| Layer | Map | Lookup |
|---|---|---|
| Generated methods | capabilities |
findCapabilities("getAccount") |
| Ergonomic helpers | ergonomicCapabilities |
findErgonomic("market") |
| Real-time streams | streamingCapabilities |
— |
The ergonomic layer follows predictable naming conventions, so helpers are guessable:
- Order builders: one verb method per kind on
trading.orders(market,limit,stop,stopLimit,trailingStop,bracket,oco,oto), plus a genericsubmitescape hatch. - Normalized REST:
get<Asset><Thing>returns canonical, symbol-keyed shapes (getStockBars,getCryptoTrades, ...);get<Asset>Candlesreturns the chart-ready columnar form. Each has a single-symbolget<Asset><Thing>For(symbol)variant (getStockBarsFor,getStockCandlesFor, ...) that returns the unwrapped value instead of a{ [symbol]: ... }map. It reads only the exact requested key: if that key is absent, it returns[](or emptyCandles) and never substitutes another symbol. - Pagination:
iterate<X>lazily yields across pages;collect<X>/collect<X>BySymboleagerly returns them. - Workflow: verb-named one-offs (
submitAndWait,closeAllPositions,getLatestPrice).
Alpaca authenticates with two distinct headers (APCA-API-KEY-ID and
APCA-API-SECRET-KEY). Pass keyId and secret directly.
const alpaca = new Alpaca({ keyId, secret });Credentials may be resolved from the standard Alpaca environment variables. Scheme selection is deterministic:
- A non-empty explicit
accessTokenselects OAuth. - Otherwise, any non-empty explicit
keyIdorsecretselects key authentication; only the missing half is read from its matching key environment variable. - With no explicit scheme,
APCA_API_OAUTH_TOKENtakes precedence over an environment key pair.
Empty explicit strings are treated as absent.
This means a process-level OAuth token cannot silently replace an explicitly selected key account, while OAuth remains available explicitly or entirely through the environment.
| Option | Environment variable |
|---|---|
keyId |
APCA_API_KEY_ID |
secret |
APCA_API_SECRET_KEY |
accessToken |
APCA_API_OAUTH_TOKEN |
// With APCA_API_KEY_ID and APCA_API_SECRET_KEY set in the environment:
const alpaca = new Alpaca();Pass an accessToken to authenticate via OAuth2; it is sent as
Authorization: Bearer <token>. An explicitly passed token takes precedence if
key fields are also present.
const alpaca = new Alpaca({ accessToken });Real-time streaming authenticates with a key/secret pair, so OAuth-only clients cannot open WebSocket streams.
Do not pass
apiKeyas a plain string — it would send the same value for both headers and Alpaca would reject it. The SDK throws a guided error if you try. To compute credentials lazily (e.g. from a vault), use the helper:import { trading, auth } from "@alpacahq/alpaca-trade-api"; const config = new trading.Configuration({ apiKey: auth.apiKeyAuth({ keyId, secret }) });
Trading defaults to paper. Switching to live is a deliberate flag, never an accidental missing host:
const live = new Alpaca({ keyId, secret, paper: false });Named hosts are exported too: trading.TRADING_PAPER_HOST,
trading.TRADING_LIVE_HOST, marketData.MARKET_DATA_HOST.
All options below are optional and conservative by default. On the Alpaca
client they are passed at the top level; on a raw Configuration they are
identical fields.
const alpaca = new Alpaca({
keyId,
secret,
// Abort a stalled request after N ms (default: 30000; set 0 to disable).
timeoutMs: 10_000,
// Use the market-data sandbox host for stock/option data (default false).
// Crypto and news streams are production-only, so this flag isn't applied there.
sandbox: false,
// Automatic retry. The Alpaca client enables this by default (3 attempts);
// pass a config to tune it or `retry: false` to disable.
retry: {
maxRetries: 2, // 1 initial + 2 retries = 3 attempts (default)
retryDelayMs: 250, // base for exponential backoff (default 250)
maxDelayMs: 5_000, // cap per delay (default 5000)
retryableStatuses: [408, 425, 429, 500, 502, 503, 504], // default
respectRetryAfter: true, // honor a Retry-After header (default true)
onRetry: (e) => console.warn(`retry ${e.attempt}/${e.maxRetries} in ${e.delayMs}ms`, e.status ?? e.error),
onGiveUp: (e) => console.error(`gave up after ${e.attempt} retries`, e.status ?? e.error),
},
// Proactive client-side rate limiting (the Alpaca client enables a safe
// default; pass a config to tune or `false` to disable). See below.
rateLimit: { maxRequests: 200, intervalMs: 60_000, maxConcurrent: 16 },
userAgent: "my-app/1.0", // default `APCA-NODE/<sdk-version> <Runtime>/<runtime-version>`; "" disables
redirect: "error", // default: reject 3xx so the APCA-API-* secret can't follow an off-host redirect ("follow" to opt out)
});The default identifies both the SDK family/version and the execution runtime,
for example APCA-NODE/4.0.0 Node/22.4.0. Runtime detection prefers Bun and
Deno before Node so their npm-compatibility globals are not mislabeled.
- On by default on the
Alpacaclient (3 attempts = 1 initial + 2 retries); pass aretryconfig to tune it orretry: falseto disable. RawApiclasses built from a bareConfigurationare off unless you setretry(same opt-in model as the rate limiter). - The
retryableStatuses(408, 425, 429, 500, 502, 503, 504by default) are retried only for safe/idempotent verbs (GET/HEAD/OPTIONS/TRACE). A non-idempotentPOST/PUT/PATCH/DELETEis never auto-retried (even on429). In particular, order-placementPOSTs are issued once and are never replayed by the transport. - Transient network failures (DNS, connection reset, TLS — surfaced as a
FetchError) are also retried, again only for the safe verbs. A deliberate abort (callerAbortSignalor thetimeoutMsdeadline) is not retried. - Backoff is exponential (doubling per attempt) from
retryDelayMs(250ms) up tomaxDelayMs(5s), with±20%jitter. ARetry-Afterheader (seconds or HTTP-date) is honored over the computed delay when present. - Observability. Pass
onRetryto be notified before each delayed retry andonGiveUpwhen a retryable failure exhausts all attempts. Each fires with aRetryEvent({ method, url, attempt, maxRetries, delayMs, status?, error? }):statusis set for status-based retries,errorfor network-error retries. These are pure observability hooks — exceptions thrown from them are swallowed so they can never break a request.
Give every order a stable, unique clientOrderId in the request body. It makes
the order auditable and gives you a key for recovery, but it is not response
replay: Alpaca rejects another order that reuses the same ID.
const clientOrderId = `mean-reversion-${crypto.randomUUID()}`;
const order = await alpaca.trading.orders.market({
symbol: "AAPL",
qty: 1,
side: "buy",
clientOrderId,
});The SDK never auto-retries the placement POST. If a FetchError leaves the
outcome ambiguous, query getOrderByClientOrderId({ clientOrderId }) before any
further submission. Do not treat a lookup miss as proof that the first request
was not accepted, and do not assume the order will eventually become visible;
apply your application's reconciliation policy before deciding what to do next.
timeoutMs is a fresh per-attempt deadline and defaults to 30000 (30s); pass
0 to disable it. Each attempt budget includes the client-side rate-limit wait,
pre middleware, fetch, error/post middleware, and successful or error
response-body consumption. Retry backoff sits outside the completed attempt
budget, and every retry starts with a new deadline.
A per-call AbortSignal (passed via initOverrides) spans the whole operation,
including retry backoff. Cancellation in any phase rejects with FetchError
whose cause is an AbortError (caller cancellation) or TimeoutError
(timeoutMs). Cancellation is never retried, and POST remains excluded from
automatic retry.
Requests default to redirect: "error", so any 3xx redirect fails fast instead
of being followed. Alpaca's APIs never redirect, and following one off-host would
forward the APCA-API-KEY-ID/APCA-API-SECRET-KEY headers to the redirect
target — unlike Authorization, custom headers are not stripped on a
cross-origin redirect, so this prevents leaking your secret. Set
redirect: "follow" (client option or per-call initOverrides) to opt back into
the platform default if you front the API with a redirecting proxy.
Alpaca enforces roughly 200 requests/minute per host. The Alpaca client
enables a safe default token bucket (~200/min, applied independently to the
trading and market-data hosts) so burst workloads self-throttle instead of
tripping 429s. Tune it with a rateLimit config or pass rateLimit: false to
opt out. When constructing raw Api classes the limiter is off unless you
set rateLimit on the Configuration.
Non-2xx responses reject with an ApiError (a ResponseError subclass) exposing
status, code, and message parsed from Alpaca's { code, message } error
envelope; the raw Response stays on .response. Branch on the status-specific
subclasses instead of magic numbers:
import { RateLimitError, NotFoundError, ApiError } from "@alpacahq/alpaca-trade-api";
try {
await alpaca.trading.orders.getOrderByOrderID({ orderId });
} catch (err) {
if (err instanceof RateLimitError) {
console.warn(`rate limited; retry in ${err.retryAfterMs}ms`, err.rateLimit);
} else if (err instanceof NotFoundError) {
console.warn("no such order");
} else if (err instanceof ApiError) {
console.error(err.status, err.code, err.message);
}
}Subclasses: AuthError (401), PermissionError (403), NotFoundError (404),
ValidationError (400/422), RateLimitError (429). Every ApiError also
surfaces rateLimit (X-RateLimit-*), retryAfterMs, and requestId —
Alpaca's X-Request-ID for the failed call. That id can't be looked up after
the fact, so log it (or include it in a support ticket) when something fails:
catch (err) {
if (err instanceof ApiError) {
console.error(`request ${err.requestId} failed`, err.status, err.message);
}
}A failed fetch itself (network/abort) rejects with FetchError.
The client methods return just the deserialized body. When you also need the
HTTP status, response headers, or X-RateLimit-* metadata of a successful
call, wrap the generated *Raw sibling (every method has one) with
withResponse. It returns a typed AlpacaApiResponse<T> —
{ data, status, headers, rateLimit }:
import { withResponse } from "@alpacahq/alpaca-trade-api";
const res = await withResponse(alpaca.trading.account.getAccountRaw());
res.data; // typed Account (same as getAccount())
res.status; // 200
res.headers.get("X-Request-ID");
res.rateLimit?.remaining; // parsed X-RateLimit-Remaining, when presentThe body stream is read once, so use res.data rather than re-reading the
underlying response.
alpaca.trading.orders is the generated OrdersApi plus one ergonomic method
per common order kind that drops the postOrder({ postOrderRequest }) wrapper,
accepts number | string amounts, and enforces the required fields per kind at
compile time. Each returns the created Order; timeInForce defaults to
"day". Supply a stable, unique clientOrderId for every live order so logs
and recovery can correlate the submission with Alpaca.
await alpaca.trading.orders.market({
symbol: "AAPL", qty: 1, side: "buy",
clientOrderId: `market-${crypto.randomUUID()}`,
});
await alpaca.trading.orders.limit({
symbol: "AAPL", qty: 1, side: "buy", limitPrice: 150,
clientOrderId: `limit-${crypto.randomUUID()}`,
});
await alpaca.trading.orders.stop({ symbol: "AAPL", qty: 1, side: "sell", stopPrice: 140 });
await alpaca.trading.orders.stopLimit({ symbol: "AAPL", qty: 1, side: "sell", stopPrice: 140, limitPrice: 139.5 });
await alpaca.trading.orders.trailingStop({ symbol: "AAPL", qty: 1, side: "sell", trailPercent: 5 });
await alpaca.trading.orders.bracket({
symbol: "AAPL", qty: 10, side: "buy", limitPrice: 150,
takeProfit: { limitPrice: 155 },
stopLoss: { stopPrice: 145, limitPrice: 144.5 },
});For shapes the typed methods don't cover (e.g. multi-leg mleg), use
alpaca.trading.orders.submit(input) or the raw postOrder. The pure builders
are also exported under the orders namespace.
A few high-level flows that would otherwise be boilerplate:
// Verify credentials/connectivity without throwing (startup health check).
const check = await alpaca.trading.validateConnection();
if (!check.ok) throw new Error(`Alpaca auth failed (${check.status ?? "network"}): ${check.message}`);
// Latest trade price as a number (undefined if unavailable).
const price = await alpaca.marketData.getLatestPrice("AAPL");
// Close every open position (optionally cancelling open orders first).
await alpaca.trading.closeAllPositions({ cancelOrders: true });
// Wait for server acknowledgement of the trade-updates subscription, place
// once, then await a terminal state without placing again on stream reconnect.
const filled = await alpaca.trading.submitAndWait(
{
type: "market",
symbol: "AAPL",
qty: 1,
side: "buy",
clientOrderId: `workflow-${crypto.randomUUID()}`,
},
{ timeoutMs: 30_000 },
);
console.log(filled.status, filled.filledAvgPrice);submitAndWait preserves a supplied client ID or creates one once, and issues
one placement request per invocation. It waits for Alpaca's server-side
listening acknowledgement before placement and never re-places after a stream
reconnect. One deadline covers stream connect, authentication, subscription,
the REST placement, and the terminal-event wait. If placement fails with an
ambiguous FetchError, the helper makes one
getOrderByClientOrderId reconciliation request and continues waiting when
appropriate; the generic order builders do not do this for you. A timeout can
still leave the placement outcome ambiguous, so this helper does not promise
exactly-once execution or eventual lookup visibility. Post-placement workflow
failures reject with SubmitAndWaitError; inspect its clientOrderId, optional
confirmed orderId, phase, placementAmbiguous, and cause. Reconcile the
client ID before resubmitting when the placement remains ambiguous.
Every paginated endpoint is iterable out of the box on the Alpaca client — you
never thread page tokens or merge per-symbol arrays. iterate* lazily yields
items across all pages; collect* eagerly returns them.
for await (const { symbol, value } of alpaca.marketData.iterateStockBars({
symbols: ["AAPL", "MSFT"],
timeframe: TimeFrame.Day,
start: new Date("2024-01-01"),
})) {
// value is a StockBar for symbol
}
const bars = await alpaca.marketData.collectStockBarsBySymbol({
symbols: "AAPL,MSFT",
timeframe: TimeFrame.Day,
start: new Date("2024-01-01"),
});
bars.AAPL; // StockBar[]
const articles = await alpaca.marketData.collectNews({ symbols: "AAPL" });
for await (const activity of alpaca.trading.iterateActivities({ activityTypes: ["FILL"] })) {
// ...
}The same pattern exists for stock/crypto/option trades, quotes, bars and
auctions, indexValues, forex rates, option snapshots/chain,
iterateOptionsContracts, and collectCorporateActions. For custom cases the
lower-level pagination namespace exposes the building blocks: paginate/
collect, paginateSymbolMap/collectBySymbol, paginateSymbolObjects/
collectSymbolObjects, and paginateCursor/collectCursor.
All token/cursor helpers track every visited value, not only the immediately
previous one. A repeated token in a longer cycle such as A → B → A stops
pagination before refetching A, after preserving all valid items or corporate
action pages fetched so far.
A multi-symbol collect*BySymbol (and the normalized get* accessors) accept a
SymbolCollectOptions to keep big back-fills cheap. By default every symbol is
multiplexed into one request whose page token is followed to exhaustion; pass
options to bound memory and parallelize:
// Cap each symbol's history (stops paging once every symbol is full).
const recent = await alpaca.marketData.getStockBars(
{ symbols: ["AAPL", "MSFT"], timeframe: TimeFrame.Minute, start },
{ maxPerSymbol: 1_000 },
);
// Fetch a large basket in parallel: split into one request per symbol,
// up to 4 in flight. The client-side rate limiter still applies.
const basket = await alpaca.marketData.getStockBars(
{ symbols: bigList, timeframe: TimeFrame.Day, start },
{ concurrency: 4, chunkSize: 1, maxPerSymbol: 5_000 },
);concurrency defaults to 1 (the single combined request); chunkSize
(default 1) controls how many symbols share each parallel request. The generic
pagination.collect/collectCursor take a maxItems cap, and
pagination.collectBySymbol takes maxPerSymbol; pagination.mapConcurrent and
pagination.chunk are exposed for custom fan-out.
Money/quantities are wire-truthful numeric strings (no float64 precision
loss). Parse or format with the values helpers; for exact arithmetic keep the
string and feed a decimal library (big.js/decimal.js, not bundled).
import { values } from "@alpacahq/alpaca-trade-api";
values.toNumber(account.buyingPower); // number | undefined
values.toNumberOr(account.cash, 0); // number with fallback
values.formatMoney(account.equity); // "$12,345.67" (display only)Build timeframes with the validated builders instead of hand-writing strings
like "1minute" (which the API rejects); the facade bar methods require the
branded TimeFrameString these return:
import { TimeFrame, TimeFrameUnit, timeFrame } from "@alpacahq/alpaca-trade-api";
timeFrame(15, TimeFrameUnit.Minute); // "15Min"
TimeFrame.Day; // preset "1Day"Multi-symbol market-data methods accept a comma-separated string or a
string[]. Time fields: trading models parse timestamps to Date, and
market-data models also type them as Date. Note that the multi-symbol/list
responses deserialize their symbol-keyed maps verbatim, so nested timestamps can
still arrive as ISO strings at runtime despite that type. The fix is to prefer
the normalized accessors below (getStockBars, the single-symbol getStockBarsFor,
etc.), which always hand back real Dates; only the raw generated map
responses (e.g. alpaca.marketData.stocks.stockBars) carry the caveat, and there
you can normalize with values.toDate / values.toISO. The same raw map
responses also surface large 64-bit ids (crypto trade .i) as strings at
runtime — see the id note under Values & types.
For nanosecond precision, every market-data Bar/Trade/Quote (both the
REST canonical accessors and the live stream) also carries timestampRaw?: string — the original RFC-3339 timestamp with full sub-millisecond digits (e.g.
"2024-01-02T03:04:05.678099211Z"). timestamp stays a convenient millisecond
Date; reach for timestampRaw when you need the exact instant Alpaca reported.
The canonical getIndexValues and getStockAuctions accessors carry the same
timestampRaw.
For 64-bit ids, both the live stream and the REST canonical trade
accessors (getStockTrades/getCryptoTrades) expose an exact string next to
the numeric field — idRaw on trades, plus (stream-only) cancel-errors, news,
and originalIdRaw/correctedIdRaw on corrections. Reach for idRaw whenever
you compare, store, or key on an id: crypto trade ids run past 2^53, where a
number silently loses precision. id stays a number (unchanged) for
convenience, and other numeric fields stay plain numbers.
Low-level/raw models: the market-data transport parses JSON losslessly, so integer fields whose value exceeds
2^53— in practice crypto trade ids — arrive as astringat runtime on the raw generated models (e.g.alpaca.marketData.crypto.cryptoTrades(...).trades[sym][i].i) even though the generated type saysnumber. Prefer the canonical accessors (which give you bothidandidRaw), or read the raw.ias the exact string. Stock/option ids, news ids, sizes, volumes, and counts stay plainnumbers.
The generated REST models keep Alpaca's compact wire keys (StockBar is
{ o, h, l, c, v, vw, n, t }), while the real-time stream surfaces readable
camelCase. The marketDataShapes namespace bridges them onto one canonical
Bar / Trade / Quote shape — the same type the streaming clients emit —
so you can backfill history over REST and append live updates over the
WebSocket without reconciling two shapes.
The Alpaca client exposes normalized accessors (auto-paginated, keyed by
symbol) alongside the raw collect*/iterate* ones:
import { Alpaca, marketDataShapes, TimeFrame } from "@alpacahq/alpaca-trade-api";
const alpaca = new Alpaca({ keyId, secret });
// REST history as canonical Bars: { [symbol]: Bar[] }
const history = await alpaca.marketData.getStockBars({
symbols: ["AAPL"], timeframe: TimeFrame.Day, start: new Date("2024-01-01"),
});
// Live bars arrive in the SAME shape - just append them.
const stream = alpaca.marketData.stockStream({ feed: "iex" });
stream.onBar((bar) => history.AAPL?.push(bar)); // bar is a Bar
stream.onConnect(() => stream.subscribeForBars(["AAPL"]));
stream.connect();Normalized accessors: getStockBars/getCryptoBars/getOptionBars,
getStockTrades/getCryptoTrades, getStockQuotes/getCryptoQuotes, and the
chart-ready getStockCandles/getCryptoCandles. Each returns a { [symbol]: T }
map; for a single symbol, the *For(symbol) variants
(getStockBarsFor, getStockCandlesFor, ... one per accessor) return the
unwrapped value directly so you skip the result[symbol] step. They use only
the exact requested map key; an absent key returns [] or empty Candles
instead of another symbol's data. For any other endpoint, normalize a raw
response yourself with the pure mappers:
marketDataShapes.toBar, toStockTrade/toCryptoTrade/toOptionTrade,
toStockQuote/toCryptoQuote/toOptionQuote, and the *BySymbol helpers.
Reshape a Bar[] into the forms plotting libraries expect:
import { toCandles, toCandlestickSeries, toLineSeries } from "@alpacahq/alpaca-trade-api";
toCandles(history.AAPL); // { time[], open[], high[], low[], close[], volume[] }
toCandles(history.AAPL, { time: "seconds" }); // unix seconds instead of epoch ms
toCandlestickSeries(history.AAPL); // [{ time, open, high, low, close }]
toLineSeries(history.AAPL, "close"); // [{ time, value }]These live in the marketDataShapes namespace too and are re-exported at the top
level. Everything here is REST-only (no ws/msgpack), so it is available from
the @alpacahq/alpaca-trade-api/rest entrypoint as well.
A few market-data gotchas are worth knowing before your first request — they come from Alpaca's data plans, not the SDK:
-
Feeds. US-equity endpoints take a
feedparameter:iex(free),sip(all US exchanges, paid), plusotc/boats. The SDK does not force a default for REST — when you omitfeed, Alpaca picks the best feed your subscription allows (iexon the free plan), so a free key won't 403 on a default request. The streaming helpers default tofeed: "iex"so a free key connects out of the box; pass{ feed: "sip" }explicitly once you have a subscription. -
The 15-minute rule. On the free plan, SIP data for the last 15 minutes is restricted. Two consequences:
- Explicitly requesting
feed: "sip"withenddefaulting to now fails with403 subscription does not permit querying recent SIP data. The SDK detects this 403 and appends guidance to the error message (pass{ feed: "iex" }, moveendback ≥15 min, or upgrade). - With
iex, recent bars exist but the trailing ~15 minutes can be sparse or empty, soend: new Date()may look like it "returns nothing". If you need a guaranteed-populated window on the free tier, setend~15 minutes in the past yourself.
The SDK deliberately does not clamp
endfor you — doing so silently would hide data that paid subscribers are entitled to. - Explicitly requesting
-
paperis irrelevant to market data. Thepaperflag only switches the trading host (paper-apivsapi); every market-data REST/stream call goes todata.alpaca.marketsregardless. Free vs paid data is governed by your subscription and thefeedparameter, not bypaper.
WebSocket clients for a market-data stream (stocks, crypto, options, news) and a
trading stream (order/account updates). Both authenticate automatically,
reconnect with backoff, dispatch current subscriptions after reconnect
authentication, and ping/pong. The API is a typed EventEmitter: register
listeners, then connect().
const stocks = alpaca.marketData.stockStream({ feed: "iex" }); // "iex" | "sip" | "delayed_sip"
stocks.onBar((bar) => pushToClients(bar)); // typed StreamBar
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, u.order.clientOrderId));
updates.onConnect(() => updates.subscribeTradeUpdates());
updates.connect();cryptoStream(), optionStream(), and newsStream() share the same surface.
Every stream also exposes:
- Awaitable authentication —
whenAuthenticated()resolves with a typedStreamAuthResult(never rejects), orwaitForAuthentication(timeoutMs?)for aboolean. Failures carry aSTREAM_AUTH_STATUS(server_rejectedwith the servercode,closed,timeout). - Reconnect lifecycle —
onReconnecting((attempt) => …)(1-based) andonReconnected(() => …)after re-authentication and re-subscription dispatch, distinct from the firstonConnect. It does not promise server acknowledgement of those subscriptions. - A custom
urlon any stream (market-data included) to route through a proxy/gateway, plus acallbackExecutorto offload listener work — a throwing listener is logged and can never break the stream.
const stocks = alpaca.marketData.stockStream({
feed: "iex",
url: "wss://proxy.internal/v2/iex", // optional: override the derived endpoint
callbackExecutor: (task) => queueMicrotask(task), // optional: offload listeners
});
stocks.onReconnecting((attempt) => console.warn(`reconnecting (attempt ${attempt})`));
stocks.onReconnected(() => console.info("reconnected; subscriptions dispatched"));
stocks.connect();
const result = await stocks.whenAuthenticated();
if (!result.authenticated) {
console.error(`stream auth failed: ${result.status} ${result.code ?? ""} ${result.message}`);
}Crypto and news streams are production-only (no sandbox endpoint): pass an explicit
urlif you must point them elsewhere; otherwisesandbox: truethrows.
Every stream — trading and market-data — shares this lifecycle surface in addition to its data handlers:
| Member | Description |
|---|---|
connect() / disconnect() |
Open / close the socket (disconnect suppresses auto-reconnect). |
onConnect / onDisconnect / onStateChange / onError |
Lifecycle + error listeners. |
onReconnecting((attempt) => …) |
Fires before each automatic reconnect (1-based attempt). |
onReconnected(() => …) |
Fires after reconnect authentication and re-subscription dispatch (not server acknowledgement). |
whenAuthenticated(): Promise<StreamAuthResult> |
Resolves with the first-auth outcome; never rejects. |
waitForAuthentication(timeoutMs?): Promise<boolean> |
true on auth, false on failure/close/timeout. |
waitForAuthenticationResult(timeoutMs?) |
Typed result; a caller-side timeout doesn't settle the real outcome. |
StreamAuthResult is { status, authenticated, code?, message } where status
is a STREAM_AUTH_STATUS (authenticated, server_rejected, closed,
timeout). Server rejections (bad credentials, etc.) include the numeric code.
Common stream options (in addition to feed/paper/sandbox): reconnect,
maxReconnectAttempts (UNLIMITED_RECONNECT_ATTEMPTS to retry forever),
backoff, initialReconnectMs, maxReconnectMs, reconnectJitter,
pingIntervalMs, pongWaitMs, url (override the endpoint), and
callbackExecutor (offload + isolate listener callbacks).
Stream state is scoped to the socket generation that created it: stale socket
callbacks and timers cannot mutate a newer connection, pings start only while
open, and manual disconnect() emits disconnect exactly once. Malformed
payloads, decode/mapper failures, trading action: "error" frames, and listener
failures surface through onError / CLIENT_ERROR without escaping callbacks
or crashing the process.
The capabilities namespace maps each generated facade accessor to its
underlying Api class and common methods; findCapabilities(name) answers
"where does this method live?":
import { capabilities, findCapabilities } from "@alpacahq/alpaca-trade-api";
findCapabilities("getAccount");
// [{ accessor: "trading.account", api: "AccountsApi", group: "trading", ... }]The ergonomic (layer 2) helpers have their own map, ergonomicCapabilities,
with a matching findErgonomic(name) lookup — so "is there a helper for this,
and where?" is answerable the same way:
import { ergonomicCapabilities, findErgonomic } from "@alpacahq/alpaca-trade-api";
findErgonomic("market");
// [{ accessor: "trading.orders", kind: "orderBuilder", wraps: "OrdersApi.postOrder", ... }]
findErgonomic("getStockBars");
// [{ accessor: "marketData", kind: "normalized", ... }]For the full, per-method listing of both layers (description + example for every method), see the generated API reference below.
Built-in middleware for logging and metrics, layered on the transport's
pre/post/onError hooks. Pass them via middleware; they observe only
(never alter the request), so they compose with retries and with each other.
import { Alpaca, middleware } from "@alpacahq/alpaca-trade-api";
const alpaca = new Alpaca({
keyId,
secret,
middleware: [
// One log line per request attempt: method, url, status, duration, requestId.
middleware.loggingMiddleware({ logger: console, level: "info" }),
// A metric per request attempt for Prometheus / StatsD / OpenTelemetry.
middleware.metricsMiddleware({
onRequest: (m) =>
statsd.timing("alpaca.request", m.durationMs, { method: m.method, status: m.status }),
}),
],
});loggingMiddleware redacts the APCA-* and Authorization headers by default
(and only includes headers at all when logHeaders: true). Both accept a
genRequestId to supply your own correlation ids.
The REST client needs nothing beyond the Node platform globals. The streaming
clients (WebSockets) pull in two small runtime dependencies — ws
and @msgpack/msgpack. At
runtime the Alpaca facade only constructs them when you actually open a stream,
but the root entrypoint's module graph statically includes them (it
re-exports the streaming namespace), so a bundler resolving
@alpacahq/alpaca-trade-api will see ws / @msgpack/msgpack.
If you only use REST — or you target an edge/browser runtime where ws cannot
run — import from the @alpacahq/alpaca-trade-api/rest
subpath (or rely on the automatic edge resolution described in
Module formats) and they are never pulled in.
If you never open a stream, import from @alpacahq/alpaca-trade-api/rest to keep the ws /
@msgpack/msgpack dependencies out of your module graph (smaller bundles,
faster cold starts). It re-exports everything except the streaming namespace.
The Alpaca facade is the same class, so all REST methods work unchanged; the
stream factories (stockStream, stream, ...) and submitAndWait throw if
called from this entrypoint — import from @alpacahq/alpaca-trade-api when you need streams.
The REST runtime graph and published declarations contain no Node, ws, or
msgpack requirements, supporting strict Node projects without DOM libraries and
edge consumers with the same facade.
import { Alpaca } from "@alpacahq/alpaca-trade-api/rest";On edge and browser runtimes you usually don't need to reach for this subpath explicitly — the root entrypoint resolves here automatically (see Module formats).
@alpacahq/alpaca-trade-api/testing provides a network-free harness so your unit tests don't
hit Alpaca. mockFetch answers canned responses by method + path; createMockAlpaca
wires one into a ready Alpaca client (dummy credentials, rate limiting off).
import { createMockAlpaca } from "@alpacahq/alpaca-trade-api/testing";
const alpaca = createMockAlpaca([
{ method: "GET", path: "/v2/account", body: { account_number: "PA42", status: "ACTIVE" } },
{ path: /\/v2\/stocks\/[A-Z]+\/trades\/latest$/, respond: ({ url }) => ({
symbol: url.pathname.split("/")[3],
trade: { p: 99.5 },
}) },
]);
const account = await alpaca.trading.account.getAccount(); // { accountNumber: "PA42", ... }
const price = await alpaca.marketData.getLatestPrice("AAPL"); // 99.5Routes match the first entry whose path (exact string or RegExp) and optional
method match; unmatched requests get your fallback or a descriptive 404. A
route's body is JSON-encoded automatically (objects) or sent verbatim
(strings); respond is the dynamic escape hatch.
The package ships both native ESM (dist/index.mjs) and CommonJS
(dist/index.js), selected via conditional exports, with per-format type
declarations and sideEffects: false for tree-shaking.
import { Alpaca } from "@alpacahq/alpaca-trade-api"; // ESMconst { Alpaca } = require("@alpacahq/alpaca-trade-api"); // CJSDual-package caveat: don't load the SDK through both
importandrequirein the same process if you rely oninstanceofagainst its exported classes (e.g.ApiError), or you may compare against two copies.
The streaming clients use Node-compatible WebSocket/EventEmitter modules, which
don't run on edge runtimes (Cloudflare Workers / workerd, Vercel Edge, Deno)
or in the browser.
To keep the root import working there, the package exports map declares
workerd, worker, edge-light, deno, and browser conditions that resolve
@alpacahq/alpaca-trade-api to the streaming-free
REST-only build automatically — so a plain
import { Alpaca } from "@alpacahq/alpaca-trade-api" builds and runs on those
targets without loading the streaming implementation.
The trade-off is the same as importing /rest directly: REST works unchanged,
but the stream factories (stockStream, stream, ...) and submitAndWait
throw. For real-time streaming, run on Node and import the root entry there.
npm install # also builds via the `prepare` script
npm run build # tsup (esbuild) -> dual ESM+CJS + types in dist/
npm run typecheck # tsc --noEmit (type authority; does not emit)
npm test # vitest
npm run generate:offline # reproduce generated REST trees from pinned specsdist/ is git-ignored and produced by the build (and automatically on
npm publish / npm pack via prepare). Runnable end-to-end examples live in
examples/.
OpenAPI Generator reproducibly derives the REST clients/models under
src/trading/{apis,models} and src/market-data/{apis,models} from the
committed pinned specs. Never hand-edit those trees; customization belongs in
tooling/ templates/overlays, while facade, pagination, streaming, and shared
transport behavior stays in hand-written modules.
Generated API docs describe only that committed snapshot. A live
npm run generate -- --dry-run --yes preview is not adoption. Real
non-interactive adoption refuses removed schemas/operations unless an owner
explicitly supplies --allow-breaking-spec-removals; see
tooling/GENERATION.md.
- One package, two namespaces. The Trading and Market Data APIs are exposed
as the
tradingandmarketDatanamespaces of a single package. This avoids collisions between the two specs, which both define aCorporateActionsApiand overlapping model names.
Every method on the facade — all generated REST methods, the real-time streaming
factories, and the ergonomic helpers — with a one-line description and a short
example. This section is generated from src/capabilities.ts
plus a hand-maintained examples map; run npm run docs:api to regenerate it (a
test fails the build if it drifts out of sync). Headings are the real facade call
paths, so every entry is individually anchor-linkable.
Operations (57)
account— getAccountaccountActivities— getAccountActivities, getAccountActivitiesByActivityTypeaccountConfigurations— getAccountConfig, patchAccountConfigassets— getV2Assets, getV2AssetsSymbolOrAssetId, getOptionsContracts, getOptionContractSymbolOrIdcalendar— calendar, legacyCalendarclock— clock, legacyClockcorporateActions— getV2CorporateActionsAnnouncements, getV2CorporateActionsAnnouncementsIdcryptoFunding— createCryptoTransferForAccount, getCryptoFundingTransfer, listCryptoFundingTransfers, getCryptoTransferEstimate, listCryptoFundingWallets, createWhitelistedAddress, deleteWhitelistedAddress, listWhitelistedAddressevents— subscribeToActivitiesSSElocates— createLocates, getLocate, listLocateQuotes, listLocatesorders— getAllOrders, postOrder, getOrderByOrderID, getOrderByClientOrderId, patchOrderByOrderId, deleteOrderByOrderID, deleteAllOrdersportfolioHistory— getAccountPortfolioHistorypositions— getAllOpenPositions, getOpenPosition, deleteAllOpenPositions, deleteOpenPosition, optionExercise, optionDoNotExercisetokenization— getTokenizationRequest, getTokenizationRequestByClientRequestID, getTokenizationRequests, postTokenizationMintwatchlists— getWatchlists, getWatchlistById, getWatchlistByName, postWatchlist, updateWatchlistById, updateWatchlistByName, addAssetToWatchlist, addAssetToWatchlistByName, removeAssetFromWatchlist, deleteWatchlistById, deleteWatchlistByName
Account details, balances, buying power and status.
Account details, balances, buying power and status.
await alpaca.trading.account.getAccount();Account activity history (fills, fees, dividends, transfers).
List account activities (fills, fees, dividends, transfers), newest first.
await alpaca.trading.accountActivities.getAccountActivities({
activityTypes: ["FILL"],
pageSize: 50,
});List activities of a single type (e.g. only fills).
await alpaca.trading.accountActivities.getAccountActivitiesByActivityType({
activityType: "FILL",
});Read and update trading account configuration.
Read the account's trading configuration.
await alpaca.trading.accountConfigurations.getAccountConfig();Update trading configuration (e.g. block short selling).
await alpaca.trading.accountConfigurations.patchAccountConfig({
accountConfigurations: { noShorting: true },
});Tradable assets, option contracts and instrument reference data.
List tradable assets, filterable by class, status and exchange.
await alpaca.trading.assets.getV2Assets({
status: "active",
assetClass: "us_equity",
});Fetch a single asset by symbol or asset id.
await alpaca.trading.assets.getV2AssetsSymbolOrAssetId({
symbolOrAssetId: "AAPL",
});List option contracts for underlying symbols (paginated).
await alpaca.trading.assets.getOptionsContracts({
underlyingSymbols: "AAPL",
limit: 100,
});Fetch a single option contract by symbol or id.
await alpaca.trading.assets.getOptionContractSymbolOrId({
symbolOrId: "AAPL250117C00150000",
});Market calendar (trading days, open/close sessions).
Market calendar (sessions) for a market and date range.
await alpaca.trading.calendar.calendar({
market: "us_equity",
start: new Date("2024-01-01"),
end: new Date("2024-01-31"),
});Legacy market-calendar endpoint (prefer calendar).
await alpaca.trading.calendar.legacyCalendar({
start: new Date("2024-01-01"),
end: new Date("2024-01-31"),
});Market clock (current time, next open/close).
Current market clock: open/closed and next open/close.
await alpaca.trading.clock.clock();Legacy market-clock endpoint (prefer clock).
await alpaca.trading.clock.legacyClock();Corporate-action announcements (splits, dividends, mergers).
Deprecated: corporate-action announcements over a date range.
await alpaca.trading.corporateActions.getV2CorporateActionsAnnouncements({
caTypes: "dividend",
since: "2024-01-01",
until: "2024-01-31",
});Deprecated: a single corporate-action announcement by id.
await alpaca.trading.corporateActions.getV2CorporateActionsAnnouncementsId({
id: "be3c368a-4c7c-4384-808e-f02c9f5a8afe",
});Crypto wallets, transfers and whitelisted withdrawal addresses.
Initiate a crypto withdrawal/transfer for the account.
await alpaca.trading.cryptoFunding.createCryptoTransferForAccount({
createCryptoTransferRequest: {
amount: "0.5",
address: "0xabc...",
asset: "ETH",
},
});Fetch a single crypto transfer by id.
await alpaca.trading.cryptoFunding.getCryptoFundingTransfer({
transferId: "f1...e9",
});List crypto transfers for the account.
await alpaca.trading.cryptoFunding.listCryptoFundingTransfers();Estimate fees for a crypto transfer.
await alpaca.trading.cryptoFunding.getCryptoTransferEstimate({
asset: "ETH",
fromAddress: "0xabc...",
toAddress: "0xdef...",
amount: "0.5",
});List the account's crypto wallets.
await alpaca.trading.cryptoFunding.listCryptoFundingWallets({
asset: "ETH",
});Whitelist a crypto withdrawal address.
await alpaca.trading.cryptoFunding.createWhitelistedAddress({
createWhitelistedAddressRequest: { address: "0xabc...", asset: "ETH" },
});Remove a whitelisted crypto address.
await alpaca.trading.cryptoFunding.deleteWhitelistedAddress({
whitelistedAddressId: "a1...c2",
});List whitelisted crypto withdrawal addresses.
await alpaca.trading.cryptoFunding.listWhitelistedAddress();Server-sent event streams for account activity.
Server-sent event stream of account activities.
await alpaca.trading.events.subscribeToActivitiesSSE({
sinceId: "20240101000000000::...",
});Easy-to-borrow locate requests, listings and quotes.
Create an easy-to-borrow locate request for a short sale.
await alpaca.trading.locates.createLocates({
createLocateRequest: { symbol: "AAPL", qty: 100 },
idempotencyKey: crypto.randomUUID(),
});Fetch a single locate request by id.
await alpaca.trading.locates.getLocate({ locateId: "loc_123" });Locate availability and pricing for one or more symbols.
await alpaca.trading.locates.listLocateQuotes({ symbols: "AAPL,TSLA" });List locate requests, filtered by status, symbol or date range.
await alpaca.trading.locates.listLocates({ status: "active" });Place, read, replace and cancel orders.
List orders, filterable by status, side and symbol.
await alpaca.trading.orders.getAllOrders({ status: "open", limit: 100 });Place one order (raw); include a stable, unique client ID for audit and recovery.
const clientOrderId = crypto.randomUUID();
await alpaca.trading.orders.postOrder({ postOrderRequest: { symbol: "AAPL", qty: "1", side: "buy", type: "market", timeInForce: "day", clientOrderId } });Fetch a single order by its order id.
await alpaca.trading.orders.getOrderByOrderID({ orderId: "f1...e9" });Look up an order by its client ID, including to reconcile an ambiguous placement before submitting again.
const clientOrderId = "the-id-recorded-before-placement";
const order = await alpaca.trading.orders.getOrderByClientOrderId({ clientOrderId });Replace (amend) an open order.
await alpaca.trading.orders.patchOrderByOrderId({
orderId: "f1...e9",
patchOrderRequest: { qty: "2" },
});Cancel a single open order.
await alpaca.trading.orders.deleteOrderByOrderID({ orderId: "f1...e9" });Cancel all open orders.
await alpaca.trading.orders.deleteAllOrders();Time series of account equity / P&L.
Time series of account equity and profit/loss.
await alpaca.trading.portfolioHistory.getAccountPortfolioHistory({
period: "1M",
timeframe: "1D",
});Open positions; close positions; exercise options.
List all open positions.
await alpaca.trading.positions.getAllOpenPositions();Fetch a single open position by symbol or asset id.
await alpaca.trading.positions.getOpenPosition({ symbolOrAssetId: "AAPL" });Liquidate every open position (optionally cancel orders first).
await alpaca.trading.positions.deleteAllOpenPositions({
cancelOrders: true,
});Close a position: whole, partial qty, or a percentage.
await alpaca.trading.positions.deleteOpenPosition({
symbolOrAssetId: "AAPL",
percentage: 50,
});Exercise a held option position.
await alpaca.trading.positions.optionExercise({
symbolOrContractId: "AAPL250117C00150000",
});Submit a do-not-exercise instruction for an option position.
await alpaca.trading.positions.optionDoNotExercise({
symbolOrContractId: "AAPL250117C00150000",
});Tokenization requests and minting.
Fetch a tokenization request by its Alpaca request id.
await alpaca.trading.tokenization.getTokenizationRequest({
tokenizationRequestId: "req_123",
});Fetch the latest tokenization request carrying a client-supplied request id.
await alpaca.trading.tokenization.getTokenizationRequestByClientRequestID({
clientRequestId: "mint-2026-001",
});List tokenization (mint/redeem) requests.
await alpaca.trading.tokenization.getTokenizationRequests({
status: "completed",
});Submit a tokenization mint request.
await alpaca.trading.tokenization.postTokenizationMint({
tokenizationMintRequest: { underlyingSymbol: "AAPL", quantity: "1" },
});Create and manage watchlists and their assets.
List all watchlists.
await alpaca.trading.watchlists.getWatchlists();Fetch a single watchlist by id.
await alpaca.trading.watchlists.getWatchlistById({
watchlistId: "f1...e9",
});Fetch a single watchlist by name.
await alpaca.trading.watchlists.getWatchlistByName({ name: "My List" });Create a watchlist with an initial set of symbols.
await alpaca.trading.watchlists.postWatchlist({
createWatchlistRequest: { name: "Tech", symbols: ["AAPL", "MSFT"] },
});Update a watchlist (name and/or symbols) by id.
await alpaca.trading.watchlists.updateWatchlistById({
watchlistId: "f1...e9",
updateWatchlistRequest: { name: "Renamed" },
});Update a watchlist (name and/or symbols) by name.
await alpaca.trading.watchlists.updateWatchlistByName({
name: "Tech",
updateWatchlistRequest: { symbols: ["AAPL"] },
});Add an asset to a watchlist by id.
await alpaca.trading.watchlists.addAssetToWatchlist({
watchlistId: "f1...e9",
addAssetToWatchlistRequest: { symbol: "NVDA" },
});Add an asset to a watchlist by name.
await alpaca.trading.watchlists.addAssetToWatchlistByName({
name: "Tech",
addAssetToWatchlistRequest: { symbol: "NVDA" },
});Remove an asset from a watchlist by id.
await alpaca.trading.watchlists.removeAssetFromWatchlist({
watchlistId: "f1...e9",
symbol: "NVDA",
});Delete a watchlist by id.
await alpaca.trading.watchlists.deleteWatchlistById({
watchlistId: "f1...e9",
});Delete a watchlist by name.
await alpaca.trading.watchlists.deleteWatchlistByName({ name: "Tech" });Operations (42)
stocks— stockBars, stockTrades, stockQuotes, stockAuctions, stockSnapshots, stockLatestBars, stockLatestQuotes, stockLatestTrades, stockMetaConditions, stockMetaExchangescrypto— cryptoBars, cryptoTrades, cryptoQuotes, cryptoSnapshots, cryptoLatestBars, cryptoLatestQuotes, cryptoLatestTrades, cryptoLatestOrderbookscryptoPerpetualFutures— cryptoPerpLatestBars, cryptoPerpLatestQuotes, cryptoPerpLatestTrades, cryptoPerpLatestOrderbooks, cryptoPerpLatestFuturesPricingfixedIncome— fixedIncomeLatestPrices, fixedIncomeLatestQuotesforex— rates, latestRatesindices— indexValues, indexLatestValueslogos— logosnews— newsoptions— optionBars, optionTrades, optionChain, optionSnapshots, optionLatestQuotes, optionLatestTrades, optionMetaConditions, optionMetaExchangesscreener— mostActives, moverscorporateActions— corporateActions
US-equity bars, trades, quotes, auctions and snapshots.
Historical bars for one or more stocks (paginated).
await alpaca.marketData.stocks.stockBars({
symbols: "AAPL,MSFT",
timeframe: "1Day",
start: new Date("2024-01-01"),
});Historical trades for one or more stocks (paginated).
await alpaca.marketData.stocks.stockTrades({
symbols: "AAPL",
start: new Date("2024-01-02"),
});Historical quotes for one or more stocks (paginated).
await alpaca.marketData.stocks.stockQuotes({
symbols: "AAPL",
start: new Date("2024-01-02"),
});Historical opening/closing auctions for stocks (paginated).
await alpaca.marketData.stocks.stockAuctions({
symbols: "AAPL",
start: new Date("2024-01-02"),
});Latest snapshot (trade, quote, bars) for one or more stocks.
await alpaca.marketData.stocks.stockSnapshots({ symbols: "AAPL,MSFT" });Latest minute bar for one or more stocks.
await alpaca.marketData.stocks.stockLatestBars({ symbols: "AAPL,MSFT" });Latest quote for one or more stocks.
await alpaca.marketData.stocks.stockLatestQuotes({ symbols: "AAPL,MSFT" });Latest trade for one or more stocks.
await alpaca.marketData.stocks.stockLatestTrades({ symbols: "AAPL,MSFT" });Trade/quote condition-code mappings for a tape.
await alpaca.marketData.stocks.stockMetaConditions({
ticktype: "trade",
tape: "A",
});Exchange-code mappings.
await alpaca.marketData.stocks.stockMetaExchanges();Crypto bars, trades, quotes, orderbooks and snapshots.
Historical crypto bars (paginated); loc selects the data region.
await alpaca.marketData.crypto.cryptoBars({
loc: "us",
symbols: "BTC/USD,ETH/USD",
timeframe: "1Day",
start: new Date("2024-01-01"),
});Historical crypto trades (paginated).
await alpaca.marketData.crypto.cryptoTrades({
loc: "us",
symbols: "BTC/USD",
start: new Date("2024-01-02"),
});Historical crypto quotes (paginated).
await alpaca.marketData.crypto.cryptoQuotes({
loc: "us",
symbols: "BTC/USD",
start: new Date("2024-01-02"),
});Latest snapshot for one or more crypto pairs.
await alpaca.marketData.crypto.cryptoSnapshots({
loc: "us",
symbols: "BTC/USD,ETH/USD",
});Latest bar for one or more crypto pairs.
await alpaca.marketData.crypto.cryptoLatestBars({
loc: "us",
symbols: "BTC/USD",
});Latest quote for one or more crypto pairs.
await alpaca.marketData.crypto.cryptoLatestQuotes({
loc: "us",
symbols: "BTC/USD",
});Latest trade for one or more crypto pairs.
await alpaca.marketData.crypto.cryptoLatestTrades({
loc: "us",
symbols: "BTC/USD",
});Latest order book for one or more crypto pairs.
await alpaca.marketData.crypto.cryptoLatestOrderbooks({
loc: "us",
symbols: "BTC/USD",
});Crypto perpetual-futures latest market data.
Latest bar for one or more crypto perpetual-futures contracts.
await alpaca.marketData.cryptoPerpetualFutures.cryptoPerpLatestBars({
loc: "global",
symbols: "BTC-PERP",
});Latest quote for one or more perpetual-futures contracts.
await alpaca.marketData.cryptoPerpetualFutures.cryptoPerpLatestQuotes({
loc: "global",
symbols: "BTC-PERP",
});Latest trade for one or more perpetual-futures contracts.
await alpaca.marketData.cryptoPerpetualFutures.cryptoPerpLatestTrades({
loc: "global",
symbols: "BTC-PERP",
});Latest order book for one or more perpetual-futures contracts.
await alpaca.marketData.cryptoPerpetualFutures.cryptoPerpLatestOrderbooks({
loc: "global",
symbols: "BTC-PERP",
});Latest funding/mark pricing for perpetual-futures contracts.
await alpaca.marketData.cryptoPerpetualFutures.cryptoPerpLatestFuturesPricing({
loc: "global",
symbols: "BTC-PERP",
});Fixed-income latest prices and quotes.
Latest fixed-income prices by ISIN.
await alpaca.marketData.fixedIncome.fixedIncomeLatestPrices({
isins: "US0378331005",
});Latest fixed-income quotes by ISIN.
await alpaca.marketData.fixedIncome.fixedIncomeLatestQuotes({
isins: "US0378331005",
tradeSize: 100,
});Foreign-exchange historical and latest rates.
Historical forex rates for currency pairs (paginated).
await alpaca.marketData.forex.rates({
currencyPairs: "EUR/USD",
timeframe: "1Day",
start: new Date("2024-01-01"),
});Latest forex rates for one or more currency pairs.
await alpaca.marketData.forex.latestRates({
currencyPairs: "EUR/USD,GBP/USD",
});Index historical and latest values.
Historical index values (paginated).
await alpaca.marketData.indices.indexValues({
symbols: "SPX",
start: new Date("2024-01-01"),
});Latest values for one or more indices.
await alpaca.marketData.indices.indexLatestValues({ symbols: "SPX" });Company logo images.
Company logo image bytes for a symbol.
await alpaca.marketData.logos.logos({ symbol: "AAPL" });Market news articles.
Latest news articles across stocks and crypto (paginated).
await alpaca.marketData.news.news({ symbols: "AAPL,TSLA", limit: 10 });Options bars, trades, chains and snapshots.
Historical option bars (paginated).
await alpaca.marketData.options.optionBars({
symbols: "AAPL250117C00150000",
timeframe: "1Day",
start: new Date("2024-01-01"),
});Historical option trades (paginated).
await alpaca.marketData.options.optionTrades({
symbols: "AAPL250117C00150000",
start: new Date("2024-01-02"),
});Snapshots for an underlying's full option chain (paginated).
await alpaca.marketData.options.optionChain({
underlyingSymbol: "AAPL",
type: "call",
});Latest snapshots for one or more option contracts.
await alpaca.marketData.options.optionSnapshots({
symbols: "AAPL250117C00150000",
});Latest quotes for one or more option contracts.
await alpaca.marketData.options.optionLatestQuotes({
symbols: "AAPL250117C00150000",
});Latest trades for one or more option contracts.
await alpaca.marketData.options.optionLatestTrades({
symbols: "AAPL250117C00150000",
});Option trade/quote condition-code mappings.
await alpaca.marketData.options.optionMetaConditions({ ticktype: "trade" });Option exchange-code mappings.
await alpaca.marketData.options.optionMetaExchanges();Market movers and most-active screeners.
Most-active stocks by volume or trade count.
await alpaca.marketData.screener.mostActives({ by: "volume", top: 10 });Top market gainers and losers.
await alpaca.marketData.screener.movers({ marketType: "stocks", top: 10 });Historical corporate-action data.
Historical corporate-action data by symbol and type (paginated).
await alpaca.marketData.corporateActions.corporateActions({
symbols: "AAPL",
types: "cash_dividend",
start: new Date("2024-01-01"),
});Open the trading-updates WebSocket (order/account events, JSON).
const updates = alpaca.trading.stream();
updates.onTradeUpdate((u) => console.log(u.event, u.order.symbol));
updates.onConnect(() => updates.subscribeTradeUpdates());
updates.connect();Open the US-equity market-data WebSocket (msgpack). Order imbalances are also available via subscribeForImbalances([...]) / onImbalance(...) — an equities-only, sparse channel that Alpaca emits mainly during limit-up/limit-down halts, so long quiet periods are expected even while subscribed.
const stocks = alpaca.marketData.stockStream({ feed: "iex" });
stocks.onBar((bar) => console.log(bar.symbol, bar.close));
stocks.onConnect(() => stocks.subscribeForBars(["AAPL", "MSFT"]));
stocks.connect();Open the crypto market-data WebSocket (msgpack).
const crypto = alpaca.marketData.cryptoStream();
crypto.onTrade((t) => console.log(t.symbol, t.price));
crypto.onConnect(() => crypto.subscribeForTrades(["BTC/USD"]));
crypto.connect();Open the options market-data WebSocket (msgpack).
const opts = alpaca.marketData.optionStream();
opts.onTrade((t) => console.log(t.symbol, t.price));
opts.onConnect(() => opts.subscribeForTrades(["AAPL250117C00150000"]));
opts.connect();Open the real-time news-headline WebSocket.
const news = alpaca.marketData.newsStream();
news.onNews((n) => console.log(n.headline));
news.onConnect(() => news.subscribeForNews(["AAPL", "TSLA"]));
news.connect();One typed builder per order kind; drops the postOrder wrapper and enforces required fields at compile time.
Place one market order (exactly one of qty/notional) with a client ID for audit and recovery.
const clientOrderId = crypto.randomUUID();
await alpaca.trading.orders.market({ symbol: "AAPL", side: "buy", qty: 1, clientOrderId });Place one limit order with a stable, unique client ID.
const clientOrderId = crypto.randomUUID();
await alpaca.trading.orders.limit({ symbol: "AAPL", side: "buy", qty: 1, limitPrice: 150, clientOrderId });Place one stop (stop-market) order with a stable, unique client ID.
const clientOrderId = crypto.randomUUID();
await alpaca.trading.orders.stop({ symbol: "AAPL", side: "sell", qty: 1, stopPrice: 140, clientOrderId });Place one stop-limit order with a stable, unique client ID.
const clientOrderId = crypto.randomUUID();
await alpaca.trading.orders.stopLimit({ symbol: "AAPL", side: "sell", qty: 1, stopPrice: 140, limitPrice: 139, clientOrderId });Place one trailing-stop order (one of trailPrice/trailPercent) with a stable, unique client ID.
const clientOrderId = crypto.randomUUID();
await alpaca.trading.orders.trailingStop({ symbol: "AAPL", side: "sell", qty: 1, trailPercent: 5, clientOrderId });Place one bracket order (entry plus take-profit and stop-loss legs) with a stable, unique client ID.
const clientOrderId = crypto.randomUUID();
await alpaca.trading.orders.bracket({ symbol: "AAPL", side: "buy", qty: 1, takeProfit: { limitPrice: 160 }, stopLoss: { stopPrice: 140 }, clientOrderId });Place one one-cancels-other order on a held position with a stable, unique client ID.
const clientOrderId = crypto.randomUUID();
await alpaca.trading.orders.oco({ symbol: "AAPL", side: "sell", qty: 1, takeProfit: { limitPrice: 160 }, stopLoss: { stopPrice: 140 }, clientOrderId });Place one one-triggers-other order with a stable, unique client ID.
const clientOrderId = crypto.randomUUID();
await alpaca.trading.orders.oto({ symbol: "AAPL", side: "buy", qty: 1, limitPrice: 150, takeProfit: { limitPrice: 160 }, clientOrderId });Place one near-raw order shape; include a stable, unique client ID and reconcile transport ambiguity explicitly.
const clientOrderId = crypto.randomUUID();
await alpaca.trading.orders.submit({ type: "market", symbol: "AAPL", side: "buy", qty: 1, clientOrderId });High-level trading flows that would otherwise be boilerplate.
Verify credentials/connectivity without throwing; returns { ok, account } or { ok: false, status, code, message }.
const check = await alpaca.trading.validateConnection();After server listening acknowledgement, place once and await a terminal update under one workflow deadline.
const clientOrderId = crypto.randomUUID();
const filled = await alpaca.trading.submitAndWait({ type: "market", symbol: "AAPL", side: "buy", qty: 1, clientOrderId }, { timeoutMs: 30_000 });Close every open position (optionally cancel open orders first).
await alpaca.trading.closeAllPositions({ cancelOrders: true });Auto-paginated iterate/collect helpers for option contracts and account activities.
Lazily yield option contracts across all pages.
for await (const contract of alpaca.trading.iterateOptionsContracts({
underlyingSymbols: "AAPL",
})) console.log(contract.symbol);Eagerly collect all option contracts across pages into one array.
const contracts = await alpaca.trading.collectOptionsContracts({
underlyingSymbols: "AAPL",
});Lazily yield account activities across all pages.
for await (const activity of alpaca.trading.iterateActivities({
activityTypes: ["FILL"],
})) console.log(activity.id);Eagerly collect all account activities across pages into one array.
const activities = await alpaca.trading.collectActivities({
activityTypes: ["FILL"],
});Lazily yield activities of a single type across all pages.
for await (const fill of alpaca.trading.iterateActivitiesByType({
activityType: "FILL",
})) console.log(fill.id);Eagerly collect activities of a single type into one array.
const fills = await alpaca.trading.collectActivitiesByType({
activityType: "FILL",
});High-level market-data flows that would otherwise be boilerplate.
Latest trade price for a symbol as a number (or undefined).
const price = await alpaca.marketData.getLatestPrice("AAPL");Auto-paginated, symbol-keyed accessors returning canonical Bar/Trade/Quote shapes (and chart-ready Candles), unified with the streaming layer. Each single-symbol *For(symbol) reads only the exact requested key and returns an empty array/Candles when absent.
Historical stock bars as canonical Bars, auto-paginated and keyed by symbol.
const bars = await alpaca.marketData.getStockBars({
symbols: ["AAPL"],
timeframe: "1Day",
start: new Date("2024-01-01"),
});Historical crypto bars as canonical Bars, keyed by symbol.
const bars = await alpaca.marketData.getCryptoBars({
loc: "us",
symbols: ["BTC/USD"],
timeframe: "1Day",
start: new Date("2024-01-01"),
});Historical option bars as canonical Bars, keyed by symbol.
const bars = await alpaca.marketData.getOptionBars({
symbols: ["AAPL250117C00150000"],
timeframe: "1Day",
start: new Date("2024-01-01"),
});Historical stock trades as canonical Trades, keyed by symbol.
const trades = await alpaca.marketData.getStockTrades({
symbols: ["AAPL"],
start: new Date("2024-01-02"),
});Historical crypto trades as canonical Trades, keyed by symbol.
const trades = await alpaca.marketData.getCryptoTrades({
loc: "us",
symbols: ["BTC/USD"],
start: new Date("2024-01-02"),
});Historical stock quotes as canonical Quotes, keyed by symbol.
const quotes = await alpaca.marketData.getStockQuotes({
symbols: ["AAPL"],
start: new Date("2024-01-02"),
});Historical crypto quotes as canonical Quotes, keyed by symbol.
const quotes = await alpaca.marketData.getCryptoQuotes({
loc: "us",
symbols: ["BTC/USD"],
start: new Date("2024-01-02"),
});Historical index values as canonical IndexValues (with full-precision timestampRaw), keyed by symbol.
const values = await alpaca.marketData.getIndexValues({
symbols: ["SPX"],
start: new Date("2024-01-02"),
});Historical stock auctions as canonical DailyAuctions (each print with full-precision timestampRaw), keyed by symbol.
const auctions = await alpaca.marketData.getStockAuctions({
symbols: ["AAPL"],
start: new Date("2024-01-02"),
});Historical stock bars as chart-ready columnar Candles, keyed by symbol.
const candles = await alpaca.marketData.getStockCandles({
symbols: ["AAPL"],
timeframe: "1Day",
start: new Date("2024-01-01"),
});Historical crypto bars as chart-ready columnar Candles, keyed by symbol.
const candles = await alpaca.marketData.getCryptoCandles({
loc: "us",
symbols: ["BTC/USD"],
timeframe: "1Day",
start: new Date("2024-01-01"),
});Exact-key stock bars as canonical Bar[]; returns [] when the requested symbol is absent.
const bars = await alpaca.marketData.getStockBarsFor("AAPL", { timeframe: "1Day", start: new Date("2024-01-01") });Exact-key crypto bars as canonical Bar[]; returns [] when the requested pair is absent.
const bars = await alpaca.marketData.getCryptoBarsFor("BTC/USD", { loc: "us", timeframe: "1Day", start: new Date("2024-01-01") });Exact-key option bars as canonical Bar[]; returns [] when the requested contract is absent.
const bars = await alpaca.marketData.getOptionBarsFor("AAPL250117C00150000", { timeframe: "1Day", start: new Date("2024-01-01") });Exact-key stock trades as canonical Trade[]; never substitutes another symbol.
const trades = await alpaca.marketData.getStockTradesFor("AAPL", { start: new Date("2024-01-02") });Exact-key crypto trades as canonical Trade[]; never substitutes another pair.
const trades = await alpaca.marketData.getCryptoTradesFor("BTC/USD", { loc: "us", start: new Date("2024-01-02") });Exact-key stock quotes as canonical Quote[]; never substitutes another symbol.
const quotes = await alpaca.marketData.getStockQuotesFor("AAPL", { start: new Date("2024-01-02") });Exact-key crypto quotes as canonical Quote[]; never substitutes another pair.
const quotes = await alpaca.marketData.getCryptoQuotesFor("BTC/USD", { loc: "us", start: new Date("2024-01-02") });Exact-key stock Candles; returns empty columns when the requested symbol is absent.
const candles = await alpaca.marketData.getStockCandlesFor("AAPL", { timeframe: "1Day", start: new Date("2024-01-01") });Exact-key crypto Candles; returns empty columns when the requested pair is absent.
const candles = await alpaca.marketData.getCryptoCandlesFor("BTC/USD", { loc: "us", timeframe: "1Day", start: new Date("2024-01-01") });Auto-paginated iterate/collect helpers across every paginated market-data endpoint; the page token is managed for you and any revisited token stops traversal.
Lazily yield { symbol, value } stock-bar records across symbols and pages.
for await (const { symbol, value } of alpaca.marketData.iterateStockBars({
symbols: ["AAPL"],
timeframe: "1Day",
start: new Date("2024-01-01"),
})) console.log(symbol, value.c);Collect stock bars merged into a { [symbol]: StockBar[] } map.
const bySymbol = await alpaca.marketData.collectStockBarsBySymbol({
symbols: ["AAPL", "MSFT"],
timeframe: "1Day",
start: new Date("2024-01-01"),
});Lazily yield stock-trade records across symbols and pages.
for await (const { symbol, value } of alpaca.marketData.iterateStockTrades({
symbols: ["AAPL"],
start: new Date("2024-01-02"),
})) console.log(symbol, value.p);Collect stock trades merged into a { [symbol]: StockTrade[] } map.
const bySymbol = await alpaca.marketData.collectStockTradesBySymbol({
symbols: ["AAPL"],
start: new Date("2024-01-02"),
});Lazily yield stock-quote records across symbols and pages.
for await (const { symbol, value } of alpaca.marketData.iterateStockQuotes({
symbols: ["AAPL"],
start: new Date("2024-01-02"),
})) console.log(symbol, value.bp);Collect stock quotes merged into a { [symbol]: StockQuote[] } map.
const bySymbol = await alpaca.marketData.collectStockQuotesBySymbol({
symbols: ["AAPL"],
start: new Date("2024-01-02"),
});Lazily yield daily-auction records across symbols and pages.
for await (const { symbol, value } of alpaca.marketData.iterateStockAuctions({
symbols: ["AAPL"],
start: new Date("2024-01-02"),
})) console.log(symbol, value.d);Collect stock auctions merged into a { [symbol]: StockDailyAuctions[] } map.
const bySymbol = await alpaca.marketData.collectStockAuctionsBySymbol({
symbols: ["AAPL"],
start: new Date("2024-01-02"),
});Lazily yield crypto-bar records across symbols and pages.
for await (const { symbol, value } of alpaca.marketData.iterateCryptoBars({
loc: "us",
symbols: ["BTC/USD"],
timeframe: "1Day",
start: new Date("2024-01-01"),
})) console.log(symbol, value.c);Collect crypto bars merged into a { [symbol]: CryptoBar[] } map.
const bySymbol = await alpaca.marketData.collectCryptoBarsBySymbol({
loc: "us",
symbols: ["BTC/USD"],
timeframe: "1Day",
start: new Date("2024-01-01"),
});Lazily yield crypto-trade records across symbols and pages.
for await (const { symbol, value } of alpaca.marketData.iterateCryptoTrades({
loc: "us",
symbols: ["BTC/USD"],
start: new Date("2024-01-02"),
})) console.log(symbol, value.p);Collect crypto trades merged into a { [symbol]: CryptoTrade[] } map.
const bySymbol = await alpaca.marketData.collectCryptoTradesBySymbol({
loc: "us",
symbols: ["BTC/USD"],
start: new Date("2024-01-02"),
});Lazily yield crypto-quote records across symbols and pages.
for await (const { symbol, value } of alpaca.marketData.iterateCryptoQuotes({
loc: "us",
symbols: ["BTC/USD"],
start: new Date("2024-01-02"),
})) console.log(symbol, value.bp);Collect crypto quotes merged into a { [symbol]: CryptoQuote[] } map.
const bySymbol = await alpaca.marketData.collectCryptoQuotesBySymbol({
loc: "us",
symbols: ["BTC/USD"],
start: new Date("2024-01-02"),
});Lazily yield option-bar records across symbols and pages.
for await (const { symbol, value } of alpaca.marketData.iterateOptionBars({
symbols: ["AAPL250117C00150000"],
timeframe: "1Day",
start: new Date("2024-01-01"),
})) console.log(symbol, value.c);Collect option bars merged into a { [symbol]: OptionBar[] } map.
const bySymbol = await alpaca.marketData.collectOptionBarsBySymbol({
symbols: ["AAPL250117C00150000"],
timeframe: "1Day",
start: new Date("2024-01-01"),
});Lazily yield option-trade records across symbols and pages.
for await (const { symbol, value } of alpaca.marketData.iterateOptionTrades({
symbols: ["AAPL250117C00150000"],
start: new Date("2024-01-02"),
})) console.log(symbol, value.p);Collect option trades merged into a { [symbol]: OptionTrade[] } map.
const bySymbol = await alpaca.marketData.collectOptionTradesBySymbol({
symbols: ["AAPL250117C00150000"],
start: new Date("2024-01-02"),
});Lazily yield index-value records across symbols and pages.
for await (const { symbol, value } of alpaca.marketData.iterateIndexValues({
symbols: ["SPX"],
start: new Date("2024-01-01"),
})) console.log(symbol, value);Collect index values merged into a { [symbol]: IndexValue[] } map.
const bySymbol = await alpaca.marketData.collectIndexValuesBySymbol({
symbols: ["SPX"],
start: new Date("2024-01-01"),
});Lazily yield forex-rate records across currency pairs and pages.
for await (const { symbol, value } of alpaca.marketData.iterateForexRates({
currencyPairs: ["EUR/USD"],
start: new Date("2024-01-01"),
})) console.log(symbol, value);Collect forex rates merged into a { [pair]: ForexRate[] } map.
const byPair = await alpaca.marketData.collectForexRatesBySymbol({
currencyPairs: ["EUR/USD"],
start: new Date("2024-01-01"),
});Lazily yield { symbol, value } option-snapshot records across symbols and pages.
for await (const { symbol, value } of alpaca.marketData.iterateOptionSnapshots({
symbols: ["AAPL250117C00150000"],
})) console.log(symbol, value);Collect option snapshots into a { [symbol]: OptionSnapshot } map.
const bySymbol = await alpaca.marketData.collectOptionSnapshotsBySymbol({
symbols: ["AAPL250117C00150000"],
});Lazily yield an underlying's option-chain snapshots across symbols and pages.
for await (const { symbol, value } of alpaca.marketData.iterateOptionChain({
underlyingSymbol: "AAPL",
})) console.log(symbol, value);Collect an option chain's snapshots into a { [symbol]: OptionSnapshot } map.
const chain = await alpaca.marketData.collectOptionChainBySymbol({
underlyingSymbol: "AAPL",
});Lazily yield a single symbol's stock bars across all pages.
for await (const bar of alpaca.marketData.iterateStockBarSingle({
symbol: "AAPL",
timeframe: "1Day",
start: new Date("2024-01-01"),
})) console.log(bar.c);Collect a single symbol's stock bars into one StockBar[] array.
const bars = await alpaca.marketData.collectStockBarSingle({
symbol: "AAPL",
timeframe: "1Day",
start: new Date("2024-01-01"),
});Lazily yield a single symbol's stock trades across all pages.
for await (const trade of alpaca.marketData.iterateStockTradeSingle({
symbol: "AAPL",
start: new Date("2024-01-02"),
})) console.log(trade.p);Collect a single symbol's stock trades into one StockTrade[] array.
const trades = await alpaca.marketData.collectStockTradeSingle({
symbol: "AAPL",
start: new Date("2024-01-02"),
});Lazily yield a single symbol's stock quotes across all pages.
for await (const quote of alpaca.marketData.iterateStockQuoteSingle({
symbol: "AAPL",
start: new Date("2024-01-02"),
})) console.log(quote.bp);Collect a single symbol's stock quotes into one StockQuote[] array.
const quotes = await alpaca.marketData.collectStockQuoteSingle({
symbol: "AAPL",
start: new Date("2024-01-02"),
});Lazily yield a single symbol's daily auctions across all pages.
for await (const auction of alpaca.marketData.iterateStockAuctionSingle({
symbol: "AAPL",
start: new Date("2024-01-02"),
})) console.log(auction.d);Collect a single symbol's daily auctions into one array.
const auctions = await alpaca.marketData.collectStockAuctionSingle({
symbol: "AAPL",
start: new Date("2024-01-02"),
});Lazily yield news articles across all pages.
for await (const article of alpaca.marketData.iterateNews({
symbols: ["AAPL"],
})) console.log(article.headline);Collect news articles into one News[] array.
const articles = await alpaca.marketData.collectNews({ symbols: ["AAPL"] });Yield valid corporate-action pages and stop before any revisited token, including longer cycles.
for await (const page of alpaca.marketData.iterateCorporateActionsPages({
symbols: ["AAPL"],
})) console.log(page.cashDividends);Merge valid corporate-action pages, stopping before any revisited pagination token.
const actions = await alpaca.marketData.collectCorporateActions({
symbols: ["AAPL"],
start: new Date("2024-01-01"),
});- Library / SDK issues: Bugs, feature requests, or questions specific to this TypeScript library → GitHub Issues.
- General Alpaca support & API discussion: Account questions, platform issues, or broader API topics → Alpaca Community Forum.
- Slack community: Chat with other developers and the Alpaca community on Slack.