@alpacahq/alpaca-trade-api
v4.0.1
Published
TypeScript SDK for the Alpaca Trading and Market Data APIs.
Readme
@alpacahq/alpaca-trade-api
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.
Requirements
- Node.js >= 20 (developed against v24) — 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.) - Strict Node TypeScript projects may omit DOM libs; the REST declarations are
portable and do not require
"dom"in the consumertsconfig.
Runtime compatibility
| 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.
Install
npm install @alpacahq/alpaca-trade-apiMigrating from 3.x? Follow the
Migration guide.
Documentation
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.
Install the agent skill
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.
Quick start: the Alpaca client
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 }));How the facade is organized
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).
Authentication
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 });Environment variables
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();OAuth
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 }) });
Paper vs live
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.
Resilience & configuration
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.
Retry semantics
- 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.
Order-submission safety
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.
Timeouts
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.
Redirects
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.
Rate limiting
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.
Typed errors
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.
Response headers (withResponse)
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.
Placing orders
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.
Workflow helpers
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.
Pagination
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.
Bounding large fetches
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.
Values & types
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.
Normalized market-data shapes (REST + streaming unified)
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.
Chart-ready 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.
Data feeds & the free-tier 15-minute delay
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.
Real-time streaming
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.
Shared stream lifecycle (all streams)
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.
Capability map (which method lives where)
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.
Observability
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.
Dependencies
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.
REST-only entrypoint
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).
Testing your integration
@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.
Module formats (ESM & CJS)
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.
Edge & browser runtimes
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.
Development
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.
Background
- 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.
API reference
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.
Trading API
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
alpaca.trading.account — AccountsApi
Account details, balances, buying power and status.
alpaca.trading.account.getAccount
Account details, balances, buying power and status.
await alpaca.trading.account.getAccount();alpaca.trading.accountActivities — AccountActivitiesApi
Account activity history (fills, fees, dividends, transfers).
alpaca.trading.accountActivities.getAccountActivities
List account activities (fills, fees, dividends, transfers), newest first.
await alpaca.trading.accountActivities.getAccountActivities({
activityTypes: ["FILL"],
pageSize: 50,
});alpaca.trading.accountActivities.getAccountActivitiesByActivityType
List activities of a single type (e.g. only fills).
await alpaca.trading.accountActivities.getAccountActivitiesByActivityType({
activityType: "FILL",
});alpaca.trading.accountConfigurations — AccountConfigurationsApi
Read and update trading account configuration.
alpaca.trading.accountConfigurations.getAccountConfig
Read the account's trading configuration.
await alpaca.trading.accountConfigurations.getAccountConfig();alpaca.trading.accountConfigurations.patchAccountConfig
Update trading configuration (e.g. block short selling).
await alpaca.trading.accountConfigurations.patchAccountConfig({
accountConfigurations: { noShorting: true },
});alpaca.trading.assets — AssetsApi
Tradable assets, option contracts and instrument reference data.
alpaca.trading.assets.getV2Assets
List tradable assets, filterable by class, status and exchange.
await alpaca.trading.assets.getV2Assets({
status: "active",
assetClass: "us_equity",
});alpaca.trading.assets.getV2AssetsSymbolOrAssetId
Fetch a single asset by symbol or asset id.
await alpaca.trading.assets.getV2AssetsSymbolOrAssetId({
symbolOrAssetId: "AAPL",
});alpaca.trading.assets.getOptionsContracts
List option contracts for underlying symbols (paginated).
await alpaca.trading.assets.getOptionsContracts({
underlyingSymbols: "AAPL",
limit: 100,
});alpaca.trading.assets.getOptionContractSymbolOrId
Fetch a single option contract by symbol or id.
await alpaca.trading.assets.getOptionContractSymbolOrId({
symbolOrId: "AAPL250117C00150000",
});alpaca.trading.calendar — CalendarApi
Market calendar (trading days, open/close sessions).
alpaca.trading.calendar.calendar
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"),
});alpaca.trading.calendar.legacyCalendar
Legacy market-calendar endpoint (prefer calendar).
await alpaca.trading.calendar.legacyCalendar({
start: new Date("2024-01-01"),
end: new Date("2024-01-31"),
});alpaca.trading.clock — ClockApi
Market clock (current time, next open/close).
alpaca.trading.clock.clock
Current market clock: open/closed and next open/close.
await alpaca.trading.clock.clock();alpaca.trading.clock.legacyClock
Legacy market-clock endpoint (prefer clock).
await alpaca.trading.clock.legacyClock();alpaca.trading.corporateActions — CorporateActionsApi
Corporate-action announcements (splits, dividends, mergers).
alpaca.trading.corporateActions.getV2CorporateActionsAnnouncements
Deprecated: corporate-action announcements over a date range.
await alpaca.trading.corporateActions.getV2CorporateActionsAnnouncements({
caTypes: "dividend",
since: "2024-01-01",
until: "2024-01-31",
});alpaca.trading.corporateActions.getV2CorporateActionsAnnouncementsId
Deprecated: a single corporate-action announcement by id.
await alpaca.trading.corporateActions.getV2CorporateActionsAnnouncementsId({
id: "be3c368a-4c7c-4384-808e-f02c9f5a8afe",
});alpaca.trading.cryptoFunding — CryptoFundingApi
Crypto wallets, transfers and whitelisted withdrawal addresses.
alpaca.trading.cryptoFunding.createCryptoTransferForAccount
Initiate a crypto withdrawal/transfer for the account.
await alpaca.trading.cryptoFunding.createCryptoTransferForAccount({
createCryptoTransferRequest: {
amount: "0.5",
address: "0xabc...",
asset: "ETH",
},
});alpaca.trading.cryptoFunding.getCryptoFundingTransfer
Fetch a single crypto transfer by id.
await alpaca.trading.cryptoFunding.getCryptoFundingTransfer({
transferId: "f1...e9",
});alpaca.trading.cryptoFunding.listCryptoFundingTransfers
List crypto transfers for the account.
await alpaca.trading.cryptoFunding.listCryptoFundingTransfers();alpaca.trading.cryptoFunding.getCryptoTransferEstimate
Estimate fees for a crypto transfer.
await alpaca.trading.cryptoFunding.getCryptoTransferEstimate({
asset: "ETH",
fromAddress: "0xabc...",
toAddress: "0xdef...",
amount: "0.5",
});alpaca.trading.cryptoFunding.listCryptoFundingWallets
List the account's crypto wallets.
await alpaca.trading.cryptoFunding.listCryptoFundingWallets({
asset: "ETH",
});alpaca.trading.cryptoFunding.createWhitelistedAddress
Whitelist a crypto withdrawal address.
await alpaca.trading.cryptoFunding.createWhitelistedAddress({
createWhitelistedAddressRequest: { address: "0xabc...", asset: "ETH" },
});alpaca.trading.cryptoFunding.deleteWhitelistedAddress
Remove a whitelisted crypto address.
await alpaca.trading.cryptoFunding.deleteWhitelistedAddress({
whitelistedAddressId: "a1...c2",
});alpaca.trading.cryptoFunding.listWhitelistedAddress
List whitelisted crypto withdrawal addresses.
await alpaca.trading.cryptoFunding.listWhitelistedAddress();alpaca.trading.events — EventsApi
Server-sent event streams for account activity.
alpaca.trading.events.subscribeToActivitiesSSE
Server-sent event stream of account activities.
await alpaca.trading.events.subscribeToActivitiesSSE({
sinceId: "20240101000000000::...",
});alpaca.trading.locates — LocatesApi
Easy-to-borrow locate requests, listings and quotes.
alpaca.trading.locates.createLocates
Create an easy-to-borrow locate request for a short sale.
await alpaca.trading.locates.createLocates({
createLocateRequest: { symbol: "AAPL", qty: 100 },
idempotencyKey: crypto.randomUUID(),
});alpaca.trading.locates.getLocate
Fetch a single locate request by id.
await alpaca.trading.locates.getLocate({ locateId: "loc_123" });alpaca.trading.locates.listLocateQuotes
Locate availability and pricing for one or more symbols.
await alpaca.trading.locates.listLocateQuotes({ symbols: "AAPL,TSLA" });alpaca.trading.locates.listLocates
List locate requests, filtered by status, symbol or date range.
await alpaca.trading.locates.listLocates({ status: "active" });alpaca.trading.orders — OrdersApi
Place, read, replace and cancel orders.
alpaca.trading.orders.getAllOrders
List orders, filterable by status, side and symbol.
await alpaca.trading.orders.getAllOrders({ status: "open", limit: 100 });alpaca.trading.orders.postOrder
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 } });alpaca.trading.orders.getOrderByOrderID
Fetch a single order by its order id.
await alpaca.trading.orders.getOrderByOrderID({ orderId: "f1...e9" });alpaca.trading.orders.getOrderByClientOrderId
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 });alpaca.trading.orders.patchOrderByOrderId
Replace (amend) an open order.
await alpaca.trading.orders.patchOrderByOrderId({
orderId: "f1...e9",
patchOrderRequest: { qty: "2" },
});alpaca.trading.orders.deleteOrderByOrderID
Cancel a single open order.
await alpaca.trading.orders.deleteOrderByOrderID({ orderId: "f1...e9" });alpaca.trading.orders.deleteAllOrders
Cancel all open orders.
await alpaca.trading.orders.deleteAllOrders();alpaca.trading.portfolioHistory — PortfolioHistoryApi
Time series of account equity / P&L.
alpaca.trading.portfolioHistory.getAccountPortfolioHistory
Time series of account equity and profit/loss.
await alpaca.trading.portfolioHistory.getAccountPortfolioHistory({
period: "1M",
timeframe: "1D",
});alpaca.trading.positions — PositionsApi
Open positions; close positions; exercise options.
alpaca.trading.positions.getAllOpenPositions
List all open positions.
await alpaca.trading.positions.getAllOpenPositions();alpaca.trading.positions.getOpenPosition
Fetch a single open position by symbol or asset id.
await alpaca.trading.positions.getOpenPosition({ symbolOrAssetId: "AAPL" });alpaca.trading.positions.deleteAllOpenPositions
Liquidate every open position (optionally cancel orders first).
await alpaca.trading.positions.deleteAllOpenPositions({
cancelOrders: true,
});alpaca.trading.positions.deleteOpenPosition
Close a position: whole, partial qty, or a percentage.
await alpaca.trading.positions.deleteOpenPosition({
symbolOrAssetId: "AAPL",
percentage: 50,
});alpaca.trading.positions.optionExercise
Exercise a held option position.
await alpaca.trading.positions.optionExercise({
symbolOrContractId: "AAPL250117C00150000",
});alpaca.trading.positions.optionDoNotExercise
Submit a do-not-exercise instruction for an option position.
await alpaca.trading.positions.optionDoNotExercise({
symbolOrContractId: "AAPL250117C00150000",
});alpaca.trading.tokenization — TokenizationApi
Tokenization requests and minting.
alpaca.trading.tokenization.getTokenizationRequest
Fetch a tokenization request by its Alpaca request id.
await alpaca.trading.tokenization.getTokenizationRequest({
tokenizationRequestId: "req_123",
});alpaca.trading.tokenization.getTokenizationRequestByClientRequestID
Fetch the latest tokenization request carrying a client-supplied request id.
await alpaca.trading.tokenization.getTokenizationRequestByClientRequestID({
clientRequestId: "mint-2026-001",
});alpaca.trading.tokenization.getTokenizationRequests
List tokenization (mint/redeem) requests.
await alpaca.trading.tokenization.getTokenizationRequests({
status: "completed",
});alpaca.trading.tokenization.postTokenizationMint
Submit a tokenization mint request.
await alpaca.trading.tokenization.postTokenizationMint({
tokenizationMintRequest: { underlyingSymbol: "AAPL", quantity: "1" },
});alpaca.trading.watchlists — WatchlistsApi
Create and manage watchlists and their assets.
alpaca.trading.watchlists.getWatchlists
List all watchlists.
await alpaca.trading.watchlists.getWatchlists();alpaca.trading.watchlists.getWatchlistById
Fetch a single watchlist by id.
await alpaca.trading.watchlists.getWatchlistById({
watchlistId: "f1...e9",
});alpaca.trading.watchlists.getWatchlistByName
Fetch a single watchlist by name.
await alpaca.trading.watchlists.getWatchlistByName({ name: "My List" });alpaca.trading.watchlists.postWatchlist
Create a watchlist with an initial set of symbols.
await alpaca.trading.watchlists.postWatchlist({
createWatchlistRequest: { name: "Tech", symbols: ["AAPL", "MSFT"] },
});alpaca.trading.watchlists.updateWatchlistById
Update a watchlist (name and/or symbols) by id.
await alpaca.trading.watchlists.updateWatchlistById({
watchlistId: "f1...e9",
updateWatchlistRequest: { name: "Renamed" },
});alpaca.trading.watchlists.updateWatchlistByName
Update a watchlist (name and/or symbols) by name.
await alpaca.trading.watchlists.updateWatchlistByName({
name: "Tech",
updateWatchlistRequest: { symbols: ["AAPL"] },
});alpaca.trading.watchlists.addAssetToWatchlist
Add an asset to a watchlist by id.
await alpaca.trading.watchlists.addAssetToWatchlist({
watchlistId: "f1...e9",
addAssetToWatchlistRequest: { symbol: "NVDA" },
});alpaca.trading.watchlists.addAssetToWatchlistByName
Add an asset to a watchlist by name.
await alpaca.trading.watchlists.addAssetToWatchlistByName({
name: "Tech",
addAssetToWatchlistRequest: { symbol: "NVDA" },
});alpaca.trading.watchlists.removeAssetFromWatchlist
Remove an asset from a watchlist by id.
await alpaca.trading.watchlists.removeAssetFromWatchlist({
watchlistId: "f1...e9",
symbol: "NVDA",
});alpaca.trading.watchlists.deleteWatchlistById
Delete a watchlist by id.
await alpaca.trading.watchlists.deleteWatchlistById({
watchlistId: "f1...e9",
});alpaca.trading.watchlists.deleteWatchlistByName
Delete a watchlist by name.
await alpaca.trading.watchlists.deleteWatchlistByName({ name: "Tech" });Market Data API
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](#alpacamarketdataindicesind
