This is a map, not the territory. It gives you the mental model, the idioms agents most often get wrong, and where to look — it deliberately omits the full API surface. Whenever you need specifics (exact method names, parameters, response fields), open the package README and grep the API reference: the README is ~2750 lines and its second half is an auto-generated, per-method reference. Do not guess method signatures from this file alone — confirm in the README or the source.
Where the source of truth lives
Paths are relative to the package root — the repo root when developing here, or
node_modules/@alpacahq/alpaca-ts-alpha/ when installed (src/ ships in the
published tarball).
| You need… | Read / search |
|---|---|
| The full per-method API (all REST methods, streams, ergonomic helpers) | README.md → the ## API reference section (search the heading, then grep for the method name) |
| The narrative docs & idioms | README.md → sections before ## API reference (Quick start, Placing orders, Pagination, Values & types, Normalized market-data shapes, Real-time streaming, …) |
| Runnable end-to-end examples | examples/trading-bot.ts, examples/marketdata-backend.ts |
| The unified client / facade wiring | src/client.ts |
| Order builders | src/orders.ts |
| Normalized bar/trade/quote shapes + chart helpers | src/marketDataShapes.ts |
| Programmatic capability maps | src/capabilities.ts |
| Shared transport (retry/timeout/rate-limit/errors) | src/core/runtime.ts |
| Streaming clients | src/streaming/ |
When unsure where a method lives, prefer the programmatic lookups (below) over guessing, then confirm against the README.
Mental model: a two-layer facade
The Alpaca client bundles every Trading and Market Data API behind one
constructor, reached via the .trading and .marketData namespaces.
- Generated (always present, uniform). Every generated REST method is
reachable raw at
alpaca.<group>.<resource>.<method>(...)— e.g.alpaca.trading.assets.getV2Assets(),alpaca.marketData.stocks.stockBars(...). Nothing is ever hidden. - Ergonomic (additive, never replaces layer 1). Hand-written conveniences sit on top: order builders, normalized market-data accessors, pagination, workflow helpers. The raw method each one wraps is still available.
The rule: if there's no ergonomic helper for what you need, the raw generated method is always there. You never have to choose between them.
Setup essentials
import { Alpaca } from "@alpacahq/alpaca-ts-alpha";
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 — a deliberate flag.
});
- Credentials resolve from env vars when omitted:
APCA_API_KEY_ID,APCA_API_SECRET_KEY,APCA_API_OAUTH_TOKEN. Explicit values win. - Never pass
apiKeyas a plain string — Alpaca needs two distinct headers and will reject a single value (the SDK throws a guided error). Use OAuth viaaccessToken, orauth.apiKeyAuth({ keyId, secret })for lazy credentials. - OAuth-only clients cannot open WebSocket streams (streaming needs key/secret).
Idioms agents get wrong (read these before writing code)
- Money & quantities are numeric
strings (wire-truthful, no float loss). Convert for display/compute with thevalueshelpers (values.toNumber,values.toNumberOr,values.formatMoney); for exact math keep the string and feed a decimal library. NeverparseFloatblindly for arithmetic. - Timeframes are branded. Don't hand-write
"1minute"(the API rejects it). Build withTimeFrame.Day/timeFrame(15, TimeFrameUnit.Minute)→ the brandedTimeFrameStringthe facade bar methods require. - Orders: prefer the ergonomic builders on
alpaca.trading.orders(market,limit,stop,stopLimit,trailingStop,bracket,oco,oto) — they drop thepostOrder({ postOrderRequest })wrapper and enforce required fields per kind at compile time. For uncovered shapes (e.g. multi-legmleg) useorders.submit(input)or the rawpostOrder. - Pagination is built in.
iterate*lazily yields across all pages;collect*/collect*BySymboleagerly return them — never thread page tokens by hand. For big back-fills passSymbolCollectOptions(maxPerSymbol,concurrency,chunkSize) to bound memory / parallelize. - REST and streaming share one shape. The normalized accessors
(
getStockBars,getCryptoTrades, …; single-symbol*For(symbol)variants; chart-readyget*Candles) return the SAMEBar/Trade/Quotetype the streams emit — backfill over REST then append live updates without remapping. The raw generated map responses (e.g.marketData.stocks.stockBars) keep Alpaca's compact wire keys ({ o, h, l, c, v, … }) and may carry ISO-string timestamps; prefer the normalized accessors ormarketDataShapes.toBaretc. - Errors are typed. Non-2xx rejects with
ApiErrorand status-specific subclasses (AuthError401,PermissionError403,NotFoundError404,ValidationError400/422,RateLimitError429). Branch on the subclass, not magic numbers. Always logerr.requestId(Alpaca'sX-Request-ID) — it can't be looked up later. Network/abort failures reject withFetchError. - Resilience is opt-in but conservative.
timeoutMs,retry(maxRetries > 0to enable; non-idempotent POSTs are never auto-retried),rateLimit(theAlpacaclient enables a safe ~200/min default; rawApiclasses do not), anduserAgentare all top-level client options. - REST-only builds: import from
@alpacahq/alpaca-ts-alpha/restto keepws/@msgpack/msgpackout of the module graph. Stream factories andsubmitAndWaitthrow from this entrypoint — import the root package for streams. On edge/browser runtimes (Cloudflare Workers/workerd, Vercel Edge, Deno, browsers) the root import auto-resolves to this REST-only build via the packageexportsconditions, so streaming is unavailable there (wscan't run on edge) but REST works without theClass extends value [object Module]crash. - ESM & CJS dual package: don't load the SDK through both
importandrequirein one process if you rely oninstanceofagainst its classes (e.g.ApiError) — you may compare against two copies.
Streaming (quick shape)
WebSocket clients are typed EventEmitters: register listeners, then
connect(). They auto-authenticate, reconnect with backoff, and re-subscribe.
const stocks = alpaca.marketData.stockStream({ feed: "iex" }); // iex | sip | delayed_sip
stocks.onBar((bar) => {/* canonical Bar */});
stocks.onConnect(() => stocks.subscribeForBars(["AAPL", "MSFT"]));
stocks.connect();
cryptoStream(), optionStream(), newsStream(), and the trading
alpaca.trading.stream() (order/account updates) share the same surface. The
submitAndWait workflow helper places an order and resolves on its terminal
state over the trading-updates stream.
Discovering anything programmatically
import { findCapabilities, findErgonomic } from "@alpacahq/alpaca-ts-alpha";
findCapabilities("getAccount"); // generated: which Api / accessor hosts it
findErgonomic("market"); // ergonomic: is there a helper, and where
capabilities / ergonomicCapabilities / streamingCapabilities are the full
maps. Use these (or grep the README ## API reference) to answer "where does X
live?" instead of guessing.
Testing integrations
@alpacahq/alpaca-ts-alpha/testing is a network-free harness: createMockAlpaca([...])
returns a ready client backed by canned responses matched by method + path; use
it so unit tests never hit Alpaca.
When you're unsure
Don't stop at this file. Open README.md and read the relevant ## section, or
grep the ## API reference for the exact method, or read the src/ module in
the table above. This skill points the way; the README and source are
authoritative.