Market Data
The Market Data API has two layers. The raw, generated endpoints
(alpaca.marketData.stocks.stockBars, alpaca.marketData.crypto.cryptoTrades,
…) remain available for complete API coverage. The ergonomic
normalized accessors auto-paginate and return canonical, symbol-keyed shapes
that match the streaming layer, so a historical Bar and a live Bar share
one type.
Normalized accessors
get<Asset><Thing> auto-paginates and returns canonical Bar / Trade /
Quote data keyed by symbol:
import { Alpaca, TimeFrame } from "@alpacahq/alpaca-trade-api";
const alpaca = new Alpaca({ keyId, secret });
// Symbol-keyed map: { AAPL: Bar[], MSFT: Bar[] }
const bars = await alpaca.marketData.getStockBars({
symbols: ["AAPL", "MSFT"],
timeframe: TimeFrame.Day,
start: new Date("2024-01-01"),
});
const trades = await alpaca.marketData.getCryptoTrades({
loc: "us",
symbols: ["BTC/USD"],
start: new Date("2024-01-02"),
});
Each accessor has a single-symbol *For(symbol) variant that returns the
unwrapped value (an array, not a symbol map):
const aapl = await alpaca.marketData.getStockBarsFor("AAPL", {
timeframe: TimeFrame.Day,
start: new Date("2024-01-01"),
});
*For always reads the exact requested key from Alpaca's symbol map. If that
key is absent it returns []; it never substitutes data from another symbol.
The candle variants return an empty Candles object (empty column arrays) when
the requested symbol is absent.
The normalized layer includes stock, crypto, and option bars; stock and crypto trades and quotes; index values; and stock auctions. Corresponding chart-ready candle and single-symbol variants are available where applicable. Browse the complete helper inventory in the Ergonomic Helpers Reference.
Normalize generated endpoint results manually
If you call generated endpoints directly, use the exported marketDataShapes
helpers to convert their raw symbol maps into the same canonical records used by
the facade and streaming clients:
import {
Alpaca,
marketDataShapes,
TimeFrame,
} from "@alpacahq/alpaca-trade-api";
const alpaca = new Alpaca({
keyId: process.env.APCA_API_KEY_ID,
secret: process.env.APCA_API_SECRET_KEY,
});
const rawBars = await alpaca.marketData.stocks.stockBars({
symbols: "AAPL,MSFT",
timeframe: TimeFrame.Day,
});
const barsBySymbol = marketDataShapes.toBarsBySymbol(rawBars.bars ?? {});
const rawTrades = await alpaca.marketData.stocks.stockTrades({ symbols: "AAPL" });
const tradesBySymbol = marketDataShapes.toTradesBySymbol(
rawTrades.trades ?? {},
marketDataShapes.toStockTrade,
);
const rawQuotes = await alpaca.marketData.stocks.stockQuotes({ symbols: "AAPL" });
const quotesBySymbol = marketDataShapes.toQuotesBySymbol(
rawQuotes.quotes ?? {},
marketDataShapes.toStockQuote,
);
Choose the asset-specific trade or quote mapper (toStockTrade,
toCryptoTrade, toStockQuote, and so on). These pure helpers stamp the symbol
from each map key and normalize fields without another network request.
Timestamp precision
Canonical Bar / Trade / Quote records include timestampRaw?: string —
the original RFC-3339 timestamp with full nanosecond precision (e.g.
"2024-01-02T03:04:05.678099211Z") — alongside the millisecond timestamp: Date. The same fields appear on the live stream, so historical and real-time
records stay identical.
The canonical index-value (getIndexValues) and stock-auction
(getStockAuctions) accessors carry the same timestampRaw on every record
(each opening/closing auction print for auctions), so those endpoints no longer
silently truncate to milliseconds when you reach for the canonical shape.
Note: raw generated models for fully-deserialized endpoints (e.g. latest orderbooks, fixed-income, perp-futures) still surface only a millisecond
Date; prefer the canonical accessors above where nanosecond precision matters.
Trade-id precision
Trade ids are 64-bit integers that can exceed JavaScript's safe integer range
(2^53) — notably crypto trade ids. The lossless market-data REST parser
converts any integer token beyond 2^53 to a string at runtime. Canonical trade
IDs then receive dedicated idRaw normalization: Trade records expose
idRaw?: string (exact) alongside id: number (convenient, but lossy past
2^53) — identical to the live stream, so historical and real-time ids match.
const trades = await alpaca.marketData.getCryptoTrades({ symbols: "BTC/USD", loc: "us" });
const t = trades["BTC/USD"][0];
t.id; // number — fine to display, lossy past 2^53
t.idRaw; // e.g. "8857581800245878123" — exact; use this to compare/store/key
Note: on raw generated models any unsafe integer can therefore arrive as a
stringat runtime even when the generated type saysnumber(for example,alpaca.marketData.crypto.cryptoTrades(...).trades[sym][i].i). Use the canonical accessors for dedicated ID normalization, and treat any raw unsafe integer as its exact string.
See Values & types for the general precision rule.
Chart-ready candles
get<Asset>Candles (and get<Asset>CandlesFor) return the same data in a
chart-ready columnar form (parallel arrays of o/h/l/c/v/…) instead
of an array of objects:
const candles = await alpaca.marketData.getStockCandles({
symbols: ["AAPL"],
timeframe: TimeFrame.Day,
start: new Date("2024-01-01"),
});
Pure helpers also reshape a canonical Bar[] for plotting libraries:
import {
toCandles,
toCandlestickSeries,
toLineSeries,
} from "@alpacahq/alpaca-trade-api";
toCandles(bars.AAPL);
toCandlestickSeries(bars.AAPL);
toLineSeries(bars.AAPL, "close");
Latest price
getLatestPrice resolves to the latest trade price for a symbol as a plain
number (or undefined if unavailable):
const price = await alpaca.marketData.getLatestPrice("AAPL");
Feeds and the free-tier delay
Feed access comes from your Alpaca data subscription, not from paper versus live trading:
- US-equity REST endpoints accept
feed:iexis the free feed;sipcovers all US exchanges and requires the corresponding subscription;otcandboatsare also supported where the endpoint allows them. - REST helpers do not force a feed. When omitted, Alpaca selects the best feed
your subscription allows, which is normally
iexon the free plan. - Stock streaming defaults to
feed: "iex"so free-plan credentials work without extra configuration. Requestsipexplicitly only when entitled. - On the free plan, recent SIP data inside the last 15 minutes is restricted.
An explicit recent
sipquery can return a guided 403. Withiex, the trailing window can be sparse or empty; if you need a reliably populated historical window, setendat least 15 minutes in the past.
The SDK does not silently clamp end, because that would hide recent data from
paid subscribers.
The paper option is irrelevant to market data. It switches trading hosts, but
market-data REST and stream calls continue to use the market-data service.
Entitlements depend on the subscription and feed.
Next steps
- Browse the curated generated-endpoint and facade overview in the Market Data API Reference. For the complete installed surface, use the published TypeScript declarations and your editor.
- Stream the same canonical shapes in Streaming & Events.
- Bound or fan out large histories with Pagination.
- Review precision and timeframe conventions in Values & types.