DocsPerpetuals

Perpetuals

Perpetual futures on stocks, ETFs, commodities, indices, currencies, pre-IPO companies and crypto, priced around the clock.

Open .md
Authx-api-key headerBase path/perpetualsWebSocketperpetuals.quotes, perpetuals.marks · perpetuals.tradesSymbol formatXAUUSDT, TSMUSDT, BTCUSDT

How the feed is built

A perpetual is a futures contract with no expiry, traded 24 hours a day, 7 days a week. The methodology in full is on the Perpetuals product page.

One composite price
Built from every independent source that lists the contract: the bid is the median of the live source bids and the ask the median of the live source asks, so the book is never crossed and no single source moves the price.
source_count
On every response and frame: how many sources stand behind the value.
Underlying class
A perpetual is an instrument type, not an asset class, so each symbol reports its underlying: equity, etf, commodity, index, forex, pre_ipo or crypto.
Units
US dollar stablecoin terms, as the contracts trade.
GET/perpetuals/symbols
Open .md

Symbol list

Every perpetual contract with its name, underlying class and source count. Open to any valid key, with or without Perpetuals on the account.

underlyingstring
Optional filter: equity, etf, commodity, index, forex, pre_ipo or crypto. An unknown value is ignored.
curl -sS "https://api.tickerlayer.com/perpetuals/symbols?underlying=commodity" \
  -H "x-api-key: <YOUR_API_KEY>"

Response 200 OK

JSON
{
  "symbols": [
    {
      "symbol": "XAUUSDT",
      "name": "Gold",
      "instrument_type": "perpetual",
      "underlying_asset_class": "commodity",
      "base": "XAU",
      "source_count": 6
    }
  ],
  "count": 8
}
source_count here is how many sources list the contract. On a price it is how many of them are live behind that value right now.
GET/perpetuals/quote/:symbol
Open .md

Latest quote

Composite best bid and ask with the displayed size summed across the contributing sources.

symbolstringRequired
Perpetual contract symbol (for example XAUUSDT, TSMUSDT, BTCUSDT). Trimmed and uppercased before lookup. Retrieve the full list from GET /perpetuals/symbols.
curl -sS "https://api.tickerlayer.com/perpetuals/quote/XAUUSDT" \
  -H "x-api-key: <YOUR_API_KEY>"

Send runs against the live API with your account key (never exposed in the browser).

Response 200 OK

JSON
{
  "symbol": "XAUUSDT",
  "bid": 4316.31,
  "ask": 4316.36,
  "bid_size": 118.049,
  "ask_size": 51.115,
  "source_count": 6,
  "timestamp": 1789640504033
}
timestamp is the event time of the freshest contributing source, in epoch milliseconds, and never steps backwards. A composite can carry one more decimal than the contract tick: the median of two sources one tick apart is a half tick. 403 perpetuals access not enabled for your account: the account does not include Perpetuals. 404 unknown symbol: the symbol is not in the perpetuals list. 404 with a no ... available message: the contract is known but has no live value right now.
GET/perpetuals/trade/last/:symbol
Open .md

Last trade

The most recent execution across sources, with the aggressor side when the source reports it.

symbolstringRequired
Perpetual contract symbol (for example XAUUSDT, TSMUSDT, BTCUSDT). Trimmed and uppercased before lookup. Retrieve the full list from GET /perpetuals/symbols.
curl -sS "https://api.tickerlayer.com/perpetuals/trade/last/TSMUSDT" \
  -H "x-api-key: <YOUR_API_KEY>"

Send runs against the live API with your account key (never exposed in the browser).

Response 200 OK

JSON
{
  "symbol": "TSMUSDT",
  "price": 423.36,
  "size": 1.5,
  "side": "buy",
  "timestamp": 1789640506413
}
Trades are the one per-event stream, so the trade tape runs on demand: a contract joins it when a client subscribes to its trades or when this route is called, and stays on it for ten minutes after the last request. The first call for a quiet contract can answer 404 no trade available; the next print fills it. side is buy, sell or null. 403 perpetuals access not enabled for your account: the account does not include Perpetuals. 404 unknown symbol: the symbol is not in the perpetuals list. 404 with a no ... available message: the contract is known but has no live value right now.
GET/perpetuals/snapshot/:symbol
Open .md

Snapshot

Quote, mark price and last trade in one call, with the contract name and underlying class. Built for first paint.

symbolstringRequired
Perpetual contract symbol (for example XAUUSDT, TSMUSDT, BTCUSDT). Trimmed and uppercased before lookup. Retrieve the full list from GET /perpetuals/symbols.
curl -sS "https://api.tickerlayer.com/perpetuals/snapshot/TSMUSDT" \
  -H "x-api-key: <YOUR_API_KEY>"

Send runs against the live API with your account key (never exposed in the browser).

Response 200 OK

JSON
{
  "symbol": "TSMUSDT",
  "name": "Taiwan Semiconductor Manufacturing Company",
  "instrument_type": "perpetual",
  "underlying_asset_class": "equity",
  "bid": 423.31,
  "ask": 423.39,
  "bid_size": 61.2,
  "ask_size": 48.7,
  "mark_price": 423.35,
  "last_price": 423.36,
  "last_size": 1.5,
  "source_count": 6,
  "timestamp": 1789640504033,
  "mark_timestamp": 1789640505932,
  "last_timestamp": 1789640506413,
  "prev_close": 421.12,
  "change": 2.23,
  "change_percent": 0.5295
}
A snapshot reads the last trade but never starts the trade tape, so polling it keeps last_* only as fresh as other demand makes it; they are null when no print is held. prev_close is the close of the last completed UTC daily bar, and change and change_percent measure the composite mid price against it (the mark price when there is no book). A perpetual has no session, so the day turns at 00:00 UTC. The three fields are null for a moment after the UTC day turns, until the new close is read. 403 perpetuals access not enabled for your account: the account does not include Perpetuals. 404 unknown symbol: the symbol is not in the perpetuals list. 404 with a no ... available message: the contract is known but has no live value right now.
GET/perpetuals/agg/:symbol/prev
Open .md

Previous bar

The most recently completed UTC daily candle for the contract.

symbolstringRequired
Perpetual contract symbol (for example XAUUSDT, TSMUSDT, BTCUSDT). Trimmed and uppercased before lookup. Retrieve the full list from GET /perpetuals/symbols.
intervalstring
Returns the most recently settled bar at that interval instead of the previous daily bar, and adds interval, bar_start, bar_end and as_of to the response. Leave it out for the daily bar.
Values1m5m15m1h4h1d
curl -sS "https://api.tickerlayer.com/perpetuals/agg/XAUUSDT/prev" \
  -H "x-api-key: <YOUR_API_KEY>"

Response 200 OK

JSON
{
  "symbol": "XAUUSDT",
  "result": {
    "o": 4305.9,
    "h": 4312.7,
    "l": 4287.5,
    "c": 4298.4,
    "v": 214380.51,
    "t": 1789257600000
  }
}
404 no bar available when the daily bar cannot be resolved yet. A bar requested with ?interval= is held for a short settle lag after it closes, so small clock differences between callers do not change which bar comes back, and it is the same bar the range endpoint returns for that window. Cache-Control and ETag mark when the value can next change.
GET/perpetuals/agg/:symbol/:multiplier/:timespan/:from/:to
Open .md

Aggregate bars (OHLCV)

Historical OHLCV bars between two UTC calendar dates (inclusive).

symbolstringRequired
Perpetual contract symbol (for example XAUUSDT, TSMUSDT, BTCUSDT). Trimmed and uppercased before lookup. Retrieve the full list from GET /perpetuals/symbols.
multipliernumberRequired
Bar size in units of timespan: 1, 5 or 15 with minute; 1 or 4 with hour; 1 with day. Other pairs return 400, and the message lists the valid ones.
timespanstringRequired
Case-insensitive. Other values return 400.
Valuesminutehourday
fromstringRequired
First UTC date, inclusive, as YYYY-MM-DD.
tostringRequired
Last UTC date, inclusive, as YYYY-MM-DD. Not before from.
limitnumber
Page size, up to 5000. results_count is the size of this page and total_count the bars in the whole range; follow next_offset until it is null.
Default500
offsetnumber
Zero-based row offset, applied after sorting.
Default0
sortstring
Order of bars by timestamp t, applied before pagination.
ValuesascdescDefaultdesc
curl -sS "https://api.tickerlayer.com/perpetuals/agg/XAUUSDT/1/day/2026-09-01/2026-09-14?sort=desc&limit=3" \
  -H "x-api-key: <YOUR_API_KEY>"

Response 200 OK

JSON
{
  "symbol": "XAUUSDT",
  "results_count": 3,
  "total_count": 14,
  "results": [
    { "o": 4298.4, "h": 4331.2, "l": 4290.1, "c": 4316.3, "v": 278600.08, "t": 1789344000000 },
    { "o": 4305.9, "h": 4312.7, "l": 4287.5, "c": 4298.4, "v": 214380.51, "t": 1789257600000 },
    { "o": 4279.2, "h": 4310.0, "l": 4271.8, "c": 4305.9, "v": 236911.37, "t": 1789171200000 }
  ],
  "next_offset": 3
}
  • Bars are built from traded prices on the contract's primary market source, one source per contract so a chart is never stitched from two series. v is that source's volume in base units, not the whole market. The live composite quote can sit a few ticks away from the latest bar close.
  • Maximum span per request: 7 days for 1 minute bars, 31 for 5 minute, 90 for 15 minute, 365 for 1 hour, 730 for 4 hour. A few contracts carry shorter windows; the 400 message states the limit for that symbol.
  • History starts when the contract was first listed, which for many perpetuals is recent. Bars are UTC, the day opens at 00:00 UTC, and the newest bar is still forming.
GET/perpetuals/mark/:symbol
Open .md

Mark price

Composite mark price: the median of the live source mark prices. The mark is the reference a perpetual market uses to value positions and trigger liquidations.

symbolstringRequired
Perpetual contract symbol (for example XAUUSDT, TSMUSDT, BTCUSDT). Trimmed and uppercased before lookup. Retrieve the full list from GET /perpetuals/symbols.
curl -sS "https://api.tickerlayer.com/perpetuals/mark/XAUUSDT" \
  -H "x-api-key: <YOUR_API_KEY>"

Send runs against the live API with your account key (never exposed in the browser).

Response 200 OK

JSON
{
  "symbol": "XAUUSDT",
  "mark_price": 4316.244,
  "source_count": 6,
  "timestamp": 1789640505932
}
403 perpetuals access not enabled for your account: the account does not include Perpetuals. 404 unknown symbol: the symbol is not in the perpetuals list. 404 with a no ... available message: the contract is known but has no live value right now.

WebSocket

Three channels on the same stream, key and subscribe message as every other feed, on the Business plan. Frames follow the stream dialect: prices and sizes are strings and the event time is ts.

ChannelCarriesSnapshot on subscribe
perpetuals.quotesThe composite top of book.The last known quote.
perpetuals.marksThe composite mark price.The last known mark.
perpetuals.tradesExecutions across sources, in arrival order.Never.
Conflation
Quotes and marks are conflated to the latest value ten times a second: a price change goes out on the next flush, a size-only change waits up to 250 ms. With source-level access, the book of each source can come tick by tick instead.
Snapshot
Replayed frames carry snapshot: true, because a quiet contract can sit unchanged for a while and silence would be ambiguous. Send snapshot: false to skip them.
Subscribe
{
  "action": "subscribe",
  "channels": ["perpetuals.quotes", "perpetuals.marks", "perpetuals.trades"],
  "symbols": ["XAUUSDT", "TSMUSDT"]
}
quote frame
{
  "type": "quote",
  "channel": "perpetuals.quotes",
  "asset": "perpetuals",
  "symbol": "XAUUSDT",
  "bid": "4316.31",
  "ask": "4316.36",
  "bid_size": "118.049",
  "ask_size": "51.115",
  "source_count": 6,
  "ts": 1789640504033
}
mark frame
{
  "type": "mark",
  "channel": "perpetuals.marks",
  "asset": "perpetuals",
  "symbol": "XAUUSDT",
  "mark_price": "4316.244",
  "source_count": 6,
  "ts": 1789640505932
}
trade frame
{
  "type": "trade",
  "channel": "perpetuals.trades",
  "asset": "perpetuals",
  "symbol": "TSMUSDT",
  "price": "423.36",
  "size": "1.5",
  "side": "buy",
  "ts": 1789640506413
}

Source-level streams

The standard feed is the composite. Enterprise accounts that run their own aggregation, such as oracle networks and quantitative desks, can also get every quote, mark and trade per source, next to the composite, on the same routes and channels. Without it, a ?sources=true request answers 403 source-level access not enabled for your account and the stream sends composite frames only. Talk to us.

FieldMeaning
source_idThe identifier of the source.
venue_symbolThe symbol on that source.
native_currencyThe currency it quotes in. Native values are never converted; USD values come next to them on request.
market_typeperpetual or spot.
REST request and response
GET /perpetuals/quote/XAUUSDT?sources=true

{
  "symbol": "XAUUSDT",
  "bid": 4316.31,
  "ask": 4316.36,
  "bid_size": 118.049,
  "ask_size": 51.115,
  "source_count": 6,
  "timestamp": 1789640504033,
  "sources": [
    {
      "source_id": "pv_01",
      "venue_symbol": "XAUUSDT",
      "native_currency": "USDT",
      "market_type": "perpetual",
      "bid": 4316.3,
      "ask": 4316.38,
      "bid_size": 15.15,
      "ask_size": 15.3,
      "timestamp": 1789640504021
    }
  ]
}
WebSocket frames
{
  "type": "venue_quote",
  "channel": "perpetuals.quotes",
  "asset": "perpetuals",
  "symbol": "XAUUSDT",
  "source_id": "pv_01",
  "venue_symbol": "XAUUSDT",
  "native_currency": "USDT",
  "market_type": "perpetual",
  "bid": "4316.3",
  "ask": "4316.38",
  "bid_size": "15.15",
  "ask_size": "15.3",
  "ts": 1789640504021
}
REST
One row per live source. /perpetuals/mark returns the same rows with mark_price in place of the book, and /perpetuals/trade/last adds the four fields to the print itself.
Stream
perpetuals.marks carries venue_mark frames and every trade frame gains the four fields. Composite frames keep their quote and mark types, so the composite is never mistaken for one source.

USD values

Source rows are priced in the stablecoin each source quotes in, USDT or USDC. Ask for USD values and every source row also carries its prices in USD, next to the native ones and never in place of them. Without the flag, rows and frames are exactly as above.

WhereFlagApplies to
RESTusd=trueThe source rows of /perpetuals/quote, /perpetuals/mark and /perpetuals/trade/last, together with sources=true.
Stream"usd": trueThe venue_quote, venue_mark and source-level trade frames of the symbols in that subscribe.
FieldMeaning
usd_bidbid in USD (quote rows).
usd_askask in USD (quote rows).
usd_mark_pricemark_price in USD (mark rows).
usd_priceprice in USD (trades with source fields).
usd_rateThe rate applied, from native_currency to USD: the mid of a USD-quoted spot market for that stablecoin. Every USD field is the native value times this rate.
Subscribe with USD values
{
  "action": "subscribe",
  "channels": ["perpetuals.quotes", "perpetuals.marks"],
  "symbols": ["XAUUSDT"],
  "usd": true
}
venue_quote frame with USD values
{
  "type": "venue_quote",
  "channel": "perpetuals.quotes",
  "asset": "perpetuals",
  "symbol": "XAUUSDT",
  "source_id": "pv_01",
  "venue_symbol": "XAUUSDT",
  "native_currency": "USDT",
  "market_type": "perpetual",
  "bid": "4316.3",
  "ask": "4316.38",
  "bid_size": "15.15",
  "ask_size": "15.3",
  "usd_bid": "4314.595062",
  "usd_ask": "4314.67503",
  "usd_rate": "0.999605",
  "ts": 1789640504021
}
No fresh rate
The USD fields are still there, as null. A rate is never assumed to be 1. Rows not priced in a stablecoin, such as the USDTARS reference book, always carry null.
Per symbol
The most recent subscribe for a symbol decides: subscribe again without usd to go back to native values only. Composite frames never carry USD fields.
Errors
usd on a channel other than the three perpetuals channels fails with UNSUPPORTED_USD, and a value that is not true or false with INVALID_USD.

Every book change

Source rows are conflated like the composite by default. Subscribe with "quote_mode": "tick_by_tick" and every change to the top of book of a source, price or size, goes out as its own venue_quote frame, in the order the source published it, with its event time in ts. Same frame and fields, plus seq, a count of that book's changes.

ValueSource rows on perpetuals.quotes
"conflated"Default. The latest book of each source per flush, like the composite.
"tick_by_tick"Every change to the top of book of each source, one frame per change.
Subscribe tick by tick
{
  "action": "subscribe",
  "channels": ["perpetuals.quotes"],
  "symbols": ["BTCUSDT", "XAUUSDT"],
  "quote_mode": "tick_by_tick"
}
venue_quote frame, tick by tick
{
  "type": "venue_quote",
  "channel": "perpetuals.quotes",
  "asset": "perpetuals",
  "symbol": "BTCUSDT",
  "source_id": "pv_02",
  "venue_symbol": "BTCUSDT",
  "native_currency": "USDT",
  "market_type": "perpetual",
  "bid": "86512.4",
  "ask": "86512.5",
  "bid_size": "3.112",
  "ask_size": "0.415",
  "seq": 1791460812437213,
  "ts": 1791460812437
}
Applies to
The venue_quote frames of the perpetuals.quotes symbols in that subscribe. Composite quote frames, venue_mark frames and trades are unchanged. It combines with usd and snapshot.
Per symbol
The most recent subscribe for a symbol decides: subscribe again with "conflated" or without quote_mode to go back.
Starting point
When a symbol starts tick by tick, the current book of each source comes first, flagged snapshot: true, then every change after it. A symbol you already stream gets that restatement whenever it switches mode, either way, even with snapshot: false, and so does every tick-by-tick symbol after a restart on our side or when source-level access comes back. A new symbol with snapshot: false gets no rows and starts with the next change.
seq
An integer that starts at a large arbitrary value (it needs 64 bits and fits a JSON number exactly), goes up by one with every change of that source's book and never goes down. A bigger step means changes were missed: frames a connection could not take, a source that dropped, a restart on our side. The same value again means the same book. Compare it only within one source and symbol; to resync, read the source rows with ?sources=true or subscribe again.
Withdrawals
Still announced with venue_status. The next venue_quote for that source and symbol means the book is back, even when its values are the same as before.
Volume
A busy book changes many times a second, mostly in size, so read the socket without blocking. Frames a connection cannot take in time are skipped, not queued, and seq shows the gap.
Connections
A symbol streams tick by tick on a limited number of connections at a time, per account and across the service. Past that, or without source-level access, the subscribe still succeeds: those symbols come conflated, and a quote_mode message after the acknowledgement names them, with QUOTE_MODE_LIMIT, scope and limit, or QUOTE_MODE_UNAVAILABLE. A capped symbol switches to tick by tick by itself once a connection frees up, announced by a quote_mode message with "tick_by_tick".
Messages
Every tick-by-tick subscribe is answered with a quote_mode message naming the symbols that got "tick_by_tick", and another for any that stay conflated. One can also arrive on its own: when a capped symbol switches, when source-level access ends, after a reconnect on our side. The latest one for a symbol is its mode, and a venue_quote that carries seq is a tick-by-tick frame.
Errors
quote_mode without perpetuals.quotes, or next to a channel other than the perpetuals ones, fails with UNSUPPORTED_QUOTE_MODE. Any other value fails with INVALID_QUOTE_MODE.
quote_mode message
{
  "type": "system",
  "event": "quote_mode",
  "channel": "perpetuals.quotes",
  "quote_mode": "conflated",
  "code": "QUOTE_MODE_LIMIT",
  "message": "These symbols already stream tick by tick on as many of this account's connections as allowed. This connection gets their conflated rows and switches to tick by tick when one frees up.",
  "symbols": ["BTCUSDT"],
  "scope": "account",
  "limit": 2
}

Normalized rows

With source-level access, "format": "normalized" renders every source row as one flat row priced in USD, the same shape for every source. The symbols in that subscribe get these rows in place of venue_quote and venue_mark; composite frames and trades do not change.

FieldMeaning
exchangeThe source id, as in source_id on the other source rows.
symbolThe source's base with USD: MSFTUSD, xyz:MSFTUSD, MSFT-USD-SWAP; USD/JPY as USDJPYUSD (xyz:USDJPYUSD).
typetop_of_book on perpetuals.quotes, mark_price on perpetuals.marks, impact_price with impact prices.
bid, mid, askUSD, as strings. Always bid <= mid <= ask, all positive. A mark row carries its price in all three.
timestampThe source's event time, ISO 8601 with milliseconds.
quoteAlways USD.
quote_sourceThe stablecoin the source quotes in, USDT or USDC.
venue_symbolThe source's own instrument.
fx_rateThe stablecoin/USD rate applied to the source prices.
fx_sourcesIds of the reference markets behind fx_rate.
fx_timestampTime of the oldest reading behind fx_rate, ISO 8601.
contractThe perpetuals symbol of the subscribe.
heartbeat_atOnly on repeats: when the row was sent again. Never on a new update.
impact_usdOnly on impact_price rows: the order size in US dollars.
Subscribe to normalized rows
{
  "action": "subscribe",
  "channels": ["perpetuals.quotes", "perpetuals.marks"],
  "symbols": ["XAUUSDT"],
  "format": "normalized"
}
Normalized row
{
  "exchange": "pv_01",
  "symbol": "XAUUSD",
  "type": "top_of_book",
  "bid": "4314.595062",
  "mid": "4314.635046",
  "ask": "4314.67503",
  "timestamp": "2026-10-10T12:00:03.477Z",
  "quote": "USD",
  "quote_source": "USDT",
  "venue_symbol": "XAUUSDT",
  "fx_rate": "0.999605",
  "fx_sources": ["fx_01", "fx_02"],
  "fx_timestamp": "2026-10-10T12:00:00.012Z",
  "contract": "XAUUSDT",
  "channel": "perpetuals.quotes"
}
Options
exchanges keeps only those sources (["pv_01", "pv_04"]). heartbeat_ms is the repeat interval, 5000 by default, 1000 to 60000, 0 for none. heartbeat_cap_ms is the price age at which repeats stop, 300000 by default, 10000 to 1800000. impact and impact_usd add impact prices. The most recent subscribe for a symbol decides; subscribe again without format to go back to the default frames.
USD rate
A new row goes out only while the reference markets agree on the stablecoin's rate and every reading behind it is at most 60 seconds old. Otherwise the row is not sent at all: no row is better than a price on a rate that cannot be confirmed. A repeat is an exact copy of a row you were sent, its rate included.
Repeats
A top of book with no real update for heartbeat_ms is sent again exactly as it was, plus heartbeat_at. Its timestamp never moves, so heartbeat_at minus timestamp is the price age. Repeats stop once that age reaches heartbeat_cap_ms, and at once when the row is withdrawn or the subscription changes. Without a rate, or while the source is not delivering, they pause and resume inside the cap. Marks are never repeated.
Silence
A withdrawn row, a source that is down and a lost rate are silence: this format has no status rows. A book seen again after a withdrawal or a restart on our side comes back as a repeat with snapshot: true, never as a new update.
Snapshots
The snapshot on subscribe and every restatement are repeats: they carry heartbeat_at and snapshot: true. A repeat with snapshot: true may hold prices you were not sent yet, for example a book that moved during a pause: take its values. A repeat without it is always an exact copy of the last row you were sent. A top of book older than heartbeat_cap_ms is not sent. With snapshot: false, quiet books start repeating one interval after the subscribe, the first time with snapshot: true.
Applies to
perpetuals.quotes and perpetuals.marks. It combines with quote_mode: tick-by-tick rows carry seq. Spot reference books have no normalized rows. A source that quotes a contract in another unit (in_composite: false) is delivered in that unit.
REST
/perpetuals/quote/{symbol}?format=normalized and the same on /perpetuals/mark answer symbol, format and rows; add exchange=pv_01 for one source. /perpetuals/symbols?format=normalized lists every source instrument this way, with base, quote_source, in_composite and impact (whether impact prices are kept for it). Impact prices are on the stream only.
Messages
A normalized subscribe is answered with a format message naming its symbols, with impact_usd when impact prices were asked for. Without source-level access the subscribe still succeeds on the composite frames, and that message carries FORMAT_UNAVAILABLE. IMPACT_UNAVAILABLE names the symbols for which no source of the subscribe keeps impact prices; the rest of the subscribe is in effect.
Errors
INVALID_FORMAT, INVALID_EXCHANGES, INVALID_HEARTBEAT and INVALID_IMPACT for values outside the above; UNSUPPORTED_FORMAT next to a channel other than the perpetuals ones; UNSUPPORTED_FORMAT_OPTION for the options without format.

Impact prices

With "impact": true in a normalized subscribe on perpetuals.quotes, each source also sends impact_price rows: the average price of a market order of impact_usd US dollars walked through that source's own book, best level first, on each side. bid is the average price of selling that amount, ask of buying it, fees not included.

Subscribe with impact prices
{
  "action": "subscribe",
  "channels": ["perpetuals.quotes"],
  "symbols": ["XAUUSDT"],
  "format": "normalized",
  "impact": true,
  "impact_usd": 10000
}
Impact row
{
  "exchange": "pv_01",
  "symbol": "XAUUSD",
  "type": "impact_price",
  "bid": "4314.211407",
  "mid": "4314.79381",
  "ask": "4315.376213",
  "timestamp": "2026-10-10T12:00:03.402Z",
  "quote": "USD",
  "quote_source": "USDT",
  "venue_symbol": "XAUUSDT",
  "fx_rate": "0.999605",
  "fx_sources": ["fx_01", "fx_02"],
  "fx_timestamp": "2026-10-10T12:00:00.012Z",
  "contract": "XAUUSDT",
  "channel": "perpetuals.quotes",
  "impact_usd": 10000
}
Size
impact_usd is one of 1000, 5000, 10000, 25000, 50000 or 100000; 10000 when left out. The order is sized in US dollars at the same agreed rate the prices are converted with.
Thin books
A side the source's book cannot fill at that size has no price, and the row is not sent: an impact price is never extrapolated past the levels a source shows. Always bid <= mid <= ask, with bid at or below the best bid and ask at or above the best ask.
Updates
A row goes out when the impact price moves; timestamp is the source's time of the book it was computed from. A quiet impact price is repeated like the top of book: the same row plus heartbeat_at every heartbeat_ms, until heartbeat_cap_ms after its timestamp. The snapshot on subscribe carries the current impact prices as repeats. A book that is lost, stops following the source, or no longer fills the size is silence: its repeats stop.
Coverage
Impact prices are kept for a set of source instruments, flagged impact: true in /perpetuals/symbols?format=normalized. A symbol without one gets the rest of its normalized rows, and an IMPACT_UNAVAILABLE message names it.

Row liveness and withdrawal

A source row's timestamp is the source's own event time, so a quiet book shows an old timestamp while the row is alive, which is common while the underlying market is closed. Do not alert on timestamp age: one rule, below, applies to every source and does not look at market hours.

fresh_book_msMilliseconds90,000
A book that changed within this window is live.
quiet_book_max_msMilliseconds1,800,000
Past 90 seconds an unchanged book stays live only while the same source's mark keeps arriving, and never longer than this.
withdraw_after_lane_loss_msMilliseconds5,000
A source connection that drops, goes silent or skips a sequence has its rows withdrawn after this, until a fresh book arrives.
On REST
A withdrawn row leaves at once and is never carried forward.
On the stream
Its own frame, venue_status, so a consumer that switches on type never meets an empty price. The next venue_quote or venue_mark for that source and symbol means it is back; no frame in between means live and unchanged.
Status route
/perpetuals/sources/status serves the same values in milliseconds.
Withdrawal frame
{
  "type": "venue_status",
  "channel": "perpetuals.quotes",
  "asset": "perpetuals",
  "symbol": "XAUUSDT",
  "source_id": "pv_02",
  "venue_symbol": "XAUUSDT",
  "native_currency": "USDT",
  "market_type": "perpetual",
  "status": "withdrawn",
  "ts": 1789640504021
}

ts is the event time of the last row delivered for that source. The same frame arrives on perpetuals.marks when a source mark is withdrawn.

Rows outside the composite

Spot reference books
Tagged market_type: spot: top of book only, no mark and no funding. Delivered, never in the composite.
Different units
A source that prices a contract in another unit than the rest, today one source on the two pre-IPO contracts. Its row is delivered raw and must not be rescaled, because the source publishes no fixed conversion factor: treat it as its own series.
Outliers
A live row too far from the cross-source median is left out of the composite for as long as it strays, while the row itself is still delivered unfiltered; source_count on the composite says how many rows counted.
ContractsLeft out beyond
Crypto1.5% from the median
Pre-IPO20% from the median
Everything else4% from the median

Rows that never enter the composite carry in_composite: false in /perpetuals/symbols?sources=true, the complete list.

GET/perpetuals/sources/status
Open .md

Per-source health

One row per source, for monitoring that runs on the source rows rather than the composite. Needs source-level access. Computed on every request from live state, so poll it as often as your alerting needs; there is no cache to wait out.

curl -sS "https://api.tickerlayer.com/perpetuals/sources/status" \
  -H "x-api-key: <YOUR_API_KEY>"

Response 200 OK

JSON
{
  "timestamp": 1789992789776,
  "thresholds": {
    "withdraw_after_lane_loss_ms": 5000,
    "fresh_book_ms": 90000,
    "quiet_book_max_ms": 1800000
  },
  "sources": [
    {
      "source_id": "pv_01",
      "role": "composite",
      "status": "up",
      "symbols_listed": 229,
      "symbols_live": 229,
      "last_update": 1789992789712,
      "oldest_live_update": 1789992731004
    }
  ],
  "fx": {
    "USDT": { "status": "ok", "rate": 0.999605, "fx_sources": ["fx_01", "fx_02"], "fx_timestamp": "2026-09-21T11:33:05.012Z" },
    "USDC": { "status": "ok", "rate": 0.99985, "fx_sources": ["fx_01", "fx_03"], "fx_timestamp": "2026-09-21T11:33:01.230Z" }
  },
  "normalization": {
    "since_process_start": { "since": 1789900000000, "prices": 1520344, "usd": 1520101, "share": 0.99984, "by_source": [] },
    "month_to_date": { "month": "2026-10", "prices": 18403210, "usd": 18399871, "share": 0.999819, "by_source": [] }
  }
}
timestampinteger
When this answer was computed, epoch milliseconds.
thresholdsobject
The row liveness rule above, in milliseconds. The same for every source.
source_idstring
Permanent identifier of the source. It never changes and is never reused.
rolestring
composite: its rows can enter the composite. reference: spot books, source rows only.
statusstring
up: at least 90% of the listed symbols are live. degraded: fewer than 90% but at least one. down: none, and every row from this source has been withdrawn.
symbols_listedinteger
Symbols this source can deliver a row for.
symbols_liveinteger
Of those, how many have a live row right now.
last_updateinteger | null
When we last received anything from this source, epoch milliseconds on our clock. Null when nothing is live.
oldest_live_updateinteger | null
Receive time of the quietest row that is still live. Null when nothing is live.
fxobject
Per stablecoin, the rate normalized rows use right now (rate, fx_sources, fx_timestamp in ISO 8601), or unavailable with the reason.
normalizationobject
Share of source prices that had an agreed USD rate when they happened, per source: since our last restart and month to date (UTC).
GET/perpetuals/symbols?sources=true
Open .md

Symbol and source universe

The symbol list with every source row each symbol can deliver. Needs source-level access. Poll it, for example once an hour, and diff it to learn about a new symbol, a new source row or a removed one before it reaches your ingest.

curl -sS "https://api.tickerlayer.com/perpetuals/symbols?sources=true" \
  -H "x-api-key: <YOUR_API_KEY>"

Response 200 OK

JSON
{
  "symbols": [
    {
      "symbol": "BNBUSDT",
      "name": "BNB",
      "instrument_type": "perpetual",
      "underlying_asset_class": "crypto",
      "base": "BNB",
      "source_count": 6,
      "sources": [
        {
          "source_id": "pv_01",
          "venue_symbol": "BNBUSDT",
          "native_currency": "USDT",
          "market_type": "perpetual",
          "in_composite": true
        },
        {
          "source_id": "pv_07",
          "venue_symbol": "BNBUSDT",
          "native_currency": "USDT",
          "market_type": "spot",
          "in_composite": false
        }
      ]
    }
  ],
  "count": 266
}
source_id values are permanent. in_composite is the fixed rule for that row, not a live verdict. A symbol that exists only as a spot row is listed with instrument_type: spot and answers with an empty composite and its source rows. Additions are also announced in the docs updates rail.