API guide

Market data API explained: REST, WebSocket, symbols and timestamps

Endpoints are the easy part. The bugs live in four quieter decisions every provider makes for you: what a symbol means, which unit a price is in, which clock a timestamp reads, and how often you may ask.

On this page
  1. What a market data API actually returns
  2. How prices travel from the market to your code
  3. Symbols: the first thing that breaks
  4. Units and number types
  5. Timestamps: which clock is this?
  6. Real-time, delayed and end-of-day data
  7. REST or WebSocket: pick per job
  8. Authentication, limits and errors
  9. A glossary to keep open
  10. Questions

Key takeaways

  • A market data API returns quotes, trades, bars and reference data for traded instruments, over REST when you ask and over WebSocket when you want updates pushed.
  • Integrations rarely break on endpoints. They break on symbol formats, price units, timestamp meaning and rate limits.
  • TickerLayer serves stocks, forex, crypto, indices, ETFs and commodities with one URL pattern and one x-api-key header.
  • A daily bar is stamped at midnight UTC of its session date, not at the close: always check which event a timestamp marks.
  • The free tier includes 3,000 REST requests a month, enough to build against real data before you pay.

A market data API is a web service that hands your code the prices of traded instruments and the reference data around them: the current bid and ask, the last trade, historical OHLCV bars, symbol lists and market hours. You call it over REST when you want one answer now, and you hold a WebSocket open when you want every change pushed to you as it happens.

That definition fits every provider. What separates a pleasant integration from a month of quiet bugs is everything around the endpoint, so this guide walks through the parts in the order they tend to break, using TickerLayer for the examples. One request first:

curlShell
curl -sS "https://api.tickerlayer.com/stocks/snapshot/US:KO" \
  -H "x-api-key: $TICKERLAYER_API_KEY"

What came back

{
  "symbol": "US:KO",1
  "bid": 88.11,
  "ask": 88.24,
  "bid_size": 400,
  "ask_size": 1000,
  "last_price": 88.24,3
  "last_timestamp": 1790589160160,4
  "prev_close": 87.81,5
  "change": 0.43,
  "change_percent": 0.4897,6
  "last_size": 150
}
  1. symbolMarket-qualified: US is the listing market, KO the ticker. A bare KO returns 400.
  2. bid / askThe best price to sell into and to buy from right now, in US dollars.
  3. last_priceThe most recent trade. It can sit inside, or briefly outside, the bid and ask.
  4. last_timestampWhen that trade happened, in Unix milliseconds, UTC. Not when you asked.
  5. prev_closeThe previous session close, the base for change and change_percent.
  6. change_percentAlready a percentage: 0.4897 means +0.49%, not +48.97%.
Response of GET /stocks/snapshot/US:KO in the US pre-market on 28 September 2026. The last trade is a pre-market print; prev_close is the Friday close.

What a market data API actually returns

Market data is the record of what buyers and sellers are doing: the prices they quote, the trades they complete, and summaries of both over time. Around it sits reference data that tells you how to read those prices: which instruments exist, when their markets open, what unit a number is in. A financial data API usually adds slower-moving data such as company fundamentals.

DataWhat it answersTickerLayer routeKey fields
QuoteWhat can I buy or sell at right now?GET /{asset}/quote/{symbol}bid, ask, bid_size, ask_size, timestamp
Last tradeWhat was the most recent deal?GET /{asset}/trade/last/{symbol}price, size, timestamp
SnapshotQuote, last trade and daily change, in one callGET /{asset}/snapshot/{symbol}last_price, prev_close, change_percent
Bars (OHLCV)How did the price move over time?GET /{asset}/agg/{symbol}/1/day/{from}/{to}o, h, l, c, v, t
SymbolsWhich instruments can I ask for?GET /{asset}/symbolssymbol, name
Market statusIs this market open, and when does it next open?GET /markets/statusstatus, next_open, next_close
The first five routes share one pattern across stocks, forex, crypto, indices, ETFs and commodities; only the asset segment changes.

Quotes here are Level 1 data: the best bid and the best ask, with their sizes. Level 2 adds the queue of orders waiting behind them at every price. Most developer APIs, TickerLayer included, serve Level 1, and it is what charts, alerts, dashboards and most trading logic actually consume.

How prices travel from the market to your code

Every price starts as an event somewhere else: an order resting on an exchange, a dealer quote, a trade printed on a venue. A market data feed is the continuous stream of those events from one source. The API sits at the other end and turns many feeds into one consistent interface. What happens in between decides how far you can trust the number.

  1. Your applicationCharts, alerts, bots, spreadsheets, AI agents.you
  2. REST and WebSocketAuthentication, entitlements and rate limits in front of api.tickerlayer.com and stream.tickerlayer.com.delivery
  3. Aggregation layerMaps every source to one symbol format, one unit and one clock, and checks prices before they are served.normalize
  4. SourcesExchanges, trading venues, dealers and reference feeds, each with its own symbols, units and timestamps.origin
The four layers of a market data API. Most integration pain comes from the normalizing layer being thin or missing.

Providers differ most in the bottom two layers. An exchange-direct feed gives you one venue's raw messages, fast and official, with that venue's licence attached. An aggregated API such as TickerLayer combines sources into derived, indicative prices: not official exchange data, but one format across asset classes and markets, which is what most applications need. If you are weighing those trade-offs, the guide to choosing financial data providers lists the questions to ask, and our data quality benchmarks show how our prices compare with independent references.

Symbols: the first thing that breaks

A symbol looks like a trivial string until you add a second market. KO is unambiguous in New York, but tickers are unique only inside one market, and the same company can list in several. That is why TickerLayer stock symbols carry a market prefix, US:KO or DE:SAP, and why a bare KO returns 400 invalid symbol instead of a guess.

AssetFormatExamples
StocksCC:TICKERUS:KO, US:BRK.B, DE:SAP, JP:7203, HK:0700
ForexSix-letter pairEURUSD, USDJPY, GBPUSD
CryptoCoin plus quote currencyBTCUSD, ETHUSD, SOLUSD
IndicesGeneric codeUS500, US30, DE40, JP225
ETFsUnprefixed codeUS500ETF, WORLDETF, USGOLD
CommoditiesReference codeXAUUSD, WTIUSD, NGASUSD
Symbol formats on TickerLayer. Every list is discoverable with GET /{asset}/symbols.

Two habits prevent most symbol bugs: normalize user input before it reaches your code (EUR/USD becomes EURUSD, BTC-USD becomes BTCUSD), and validate against the provider's symbol list instead of guessing. The ticker symbol guide covers formats across markets, including numeric codes in Asia and share-class suffixes.

Units and number types

A price is a number plus a unit, and the unit is usually implied. Currency pairs are priced in the second currency, so USDJPY at 157.10 means yen per dollar. Stocks are priced in the currency of their listing. Commodities are where implied units bite: SUGARUSD is quoted in US cents per pound, so 18.54 means 18.54 cents, not dollars. Bond yields come with an explicit "unit": "percent", and the bond snapshot reports the daily move twice, as change in percentage points and as change_bps in basis points.

Number types matter too. REST responses send JSON numbers. The WebSocket stream sends crypto, forex and stock prices as strings ("bid":"82849.99"), which keeps the exact digits but makes float() or Number() your job. And JSON numbers are binary floating point: one captured index snapshot carried prev_close as 7753.800020000001. Round for display, and use a decimal type when you add up money.

Timestamps: which clock is this?

Every TickerLayer price carries a Unix timestamp in milliseconds, UTC: a 13-digit integer such as 1790591112968, which is 10:25:12.968 UTC on 28 September 2026. The format is the easy part. The question to ask of every timestamp is which event it marks.

FieldWhereWhat it marks
timestampREST quote and last tradeThe time of the quote or trade, in Unix milliseconds
last_timestampREST snapshotThe last trade, which can be hours old outside trading hours
tBarsThe start of the bar; a daily bar is stamped at 00:00 UTC of its session date
tsWebSocket framesThe update; a snapshot frame keeps its original time, so it can be older than its arrival
next_open, next_closeMarket statusISO-8601 strings in UTC, with the market's local_time alongside
Time fields across REST, WebSocket and market status responses.

The daily bar convention catches everyone once. The US:KO bar for Friday 25 September 2026 has t = 1790294400000, which is midnight UTC, although the session ran from 13:30 to 20:00 UTC. Nothing is wrong: the stamp names the session date, not the closing bell. The guide to Unix timestamps in milliseconds has conversion code for every language and the time-zone traps that come with it.

Real-time, delayed and end-of-day data

Real-time data is delivered as soon as practical after the market event, with no deliberate hold. Delayed data is held back on purpose, commonly by 15 minutes, because many licences price live display far above delayed display. End-of-day data arrives once, after the close. A real-time market data API means the first category; the rest of the latency conversation is about how far below a second you truly need to be.

Where kinds of market data sit on the clock

  1. ~10 µsCo-located exchange feed
  2. ~100 msStreaming over the public internet
  3. ~5 sREST polling every 10 s, average wait
  4. 15 minDelayed display data
  5. 1 dayEnd-of-day files
Orders of magnitude for intuition, not measurements of any product. The axis is logarithmic.

TickerLayer's API is real-time, with two qualifications worth stating. The prices are derived and indicative rather than official exchange data. And for stocks, latency varies by market, so a few markets are delayed. The public symbol pages on this website show prices 15 minutes delayed; the API does not.

REST or WebSocket: pick per job

REST

  • You ask; the server answers once.
  • Best for history, snapshots, page loads and scheduled jobs.
  • Each call counts against a per-second limit and a monthly quota.
  • Stateless: easy to cache, retry and run from serverless code.

WebSocket

  • You subscribe once; the server pushes every update.
  • Best for live prices on many symbols, trade tapes and alerts.
  • Limited by connections and distinct symbols, not by request count.
  • Stateful: you own reconnects, heartbeats and resubscribes.
Most production apps use both: REST to load history and fill gaps, WebSocket for the live edge.

A WebSocket session is short to set up. Connect to wss://stream.tickerlayer.com/?apiKey=..., wait for the ready frame, and send one message:

subscribeJSON
{"action": "subscribe", "channels": ["crypto.quotes", "crypto.trades"], "symbols": ["BTCUSD"]}

The server confirms with a subscribed frame and starts pushing quotes and trades. For symbols with a recent value it first sends that last-known value marked "snapshot": true, so a screen is not blank while it waits for the first tick; add "snapshot": false for live ticks only. The trade-offs, with the request arithmetic worked through, are in WebSocket vs REST.

Authentication, limits and errors

Send the key in the x-api-key header

Market data APIs authenticate with a key, and the key has to travel somewhere. TickerLayer REST expects it in the x-api-key header on every request. A custom header keeps the key out of URLs, which end up in server logs, browser history and proxy caches; that is also why the older ?apiKey= query form is accepted on REST only as a legacy fallback. The WebSocket upgrade is the exception: browsers cannot set custom headers on a WebSocket, so the stream takes the key as ?apiKey= on the connection URL.

snapshot.pyPython
import os

import requests

resp = requests.get(
    "https://api.tickerlayer.com/stocks/snapshot/US:KO",
    headers={"x-api-key": os.environ["TICKERLAYER_API_KEY"]},
    timeout=10,
)
resp.raise_for_status()
snap = resp.json()
print(f'{snap["symbol"]} last {snap["last_price"]} ({snap["change_percent"]:+.2f}% vs {snap["prev_close"]})')
snapshot.mjs (Node 18+)JavaScript
const res = await fetch("https://api.tickerlayer.com/stocks/snapshot/US:KO", {
  headers: { "x-api-key": process.env.TICKERLAYER_API_KEY },
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const snap = await res.json();
console.log(`${snap.symbol} bid ${snap.bid} ask ${snap.ask} last ${snap.last_price}`);
Output (28 September 2026, pre-market)
US:KO last 88.16 (+0.40% vs 87.81)
US:KO bid 88.15 ask 88.2 last 88.16

Keep the key on a server. A key embedded in a web page is visible to anyone who opens the developer tools, and browser calls to the REST API are accepted only from approved origins anyway.

Errors and limits to handle on day one

StatusMeaningWhat to do
400Malformed request, such as a bare KO or an unsupported bar intervalFix the request; do not retry
401Missing or invalid keyCheck the header name and the key
403Your plan does not include this dataUpgrade or drop the call; retrying will not help
404Unknown symbol or no dataValidate symbols against GET /{asset}/symbols
429Per-second limit or monthly quota reachedHonour Retry-After, back off with jitter
503Temporary unavailabilityRetry with backoff
Status codes every market data client should branch on.

Every authenticated response carries X-RateLimit-Limit and X-RateLimit-Remaining for the current one-second window, so a well-behaved client can pace itself before it ever sees a 429. The free tier includes 3,000 REST requests a month, and paid plans are sold per feed. Retry code that tells the two kinds of 429 apart is in 429 Too Many Requests.

A glossary to keep open

  • Bid and askThe best price a buyer will pay and the best price a seller will accept. The gap between them is the spread.
  • MidThe midpoint of bid and ask. What most charts plot, and a price nobody actually trades at.
  • LastThe price of the most recent trade. In a quiet market it can lag the quote by minutes.
  • OHLCVOpen, high, low, close and volume for one interval: the bar behind every candlestick.
  • SnapshotQuote, last trade and daily change in one response, or the last-known value a stream sends on subscribe.
  • TickA single update: one new quote or one new trade. Streams deliver ticks; bars summarize them.
  • EntitlementWhat a key may access: which feeds, which markets, which transports.
  • AggregationCombining several sources into one price per instrument, in one format.
  • SessionThe hours a market trades, including pre-market and after-hours for US stocks.

Go deeper by asset class

Questions

What is a market data API?

A web service that returns prices and reference data for traded instruments to your code: quotes, trades, historical bars, symbol lists and market hours. It is usually offered over REST for requests and over WebSocket for streaming.

What is the difference between real-time and delayed market data?

Real-time data is delivered as soon as practical after the market event. Delayed data is held back on purpose, commonly by 15 minutes, usually because a licence for live display costs more.

Is there a free market data API?

Yes. The TickerLayer free tier includes 3,000 REST requests a month with no card required, enough to prototype. WebSocket streaming comes with paid plans, and free accounts can request a trial from the dashboard.

What is the x-api-key header?

A custom HTTP request header that carries your API key. Sending the key in a header rather than in the URL keeps it out of server logs and browser history.

Should I use REST or WebSocket for market data?

Use REST for history, snapshots and occasional lookups, and a WebSocket when you need continuous live prices on more than a few symbols. Most production apps use both.

What is a market data feed?

The continuous stream of quotes and trades from one source, such as an exchange or a trading venue. An API is the interface you use to read one or more feeds.

Keep reading

Ready to integrate?

Start with the free tier, explore the docs, and connect via REST or WebSocket in minutes.