DocsPerpetuals

Perpetuals

Perpetual futures on stocks, ETFs, commodities, indices, currencies, pre-IPO companies and crypto, priced around the clock. All routes live under /perpetuals.

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, and it trades 24 hours a day, 7 days a week. Each symbol here is one composite price built from every independent market source that lists the contract: the bid is the median of the live source bids and the ask is the median of the live source asks, so the book is never crossed and a single source cannot move the price. Every response and every frame carries source_count, the number of sources behind that value. The feed is source neutral: one normalized price per contract. A perpetual is an instrument type rather than an asset class, so each symbol also reports the class of its underlying (equity, etf, commodity, index, forex, pre_ipo or crypto). Prices are quoted in US dollar stablecoin terms, as the contracts trade. See the Perpetuals product page for the methodology in full.
GET/perpetuals/symbols

Symbols

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

ParameterTypeDescription
underlyingstringOptional 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

Latest quote

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

ParameterTypeDescription
symbolreqstringPerpetual 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/mark/:symbol

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.

ParameterTypeDescription
symbolreqstringPerpetual 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.
GET/perpetuals/trade/last/:symbol

Last trade

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

ParameterTypeDescription
symbolreqstringPerpetual 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

Snapshot

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

ParameterTypeDescription
symbolreqstringPerpetual 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/:multiplier/:timespan/:from/:to

Aggregates: OHLCV range

Historical OHLCV bars between two UTC calendar dates (inclusive). Sorted then paginated. next_offset is null when exhausted.

ParameterTypeDescription
symbolreqstringPerpetual contract symbol (for example XAUUSDT, TSMUSDT, BTCUSDT). Trimmed and uppercased before lookup. Retrieve the full list from GET /perpetuals/symbols.
multiplierreqnumberInterval multiplier. Valid pairs: 1, 5, 15 with minute; 1, 4 with hour; 1 with day.
timespanreqstringminute · hour · day — case-insensitive. Other values return 400.
fromreqstringUTC date start, inclusive. Format: YYYY-MM-DD.
toreqstringUTC date end, inclusive. Format: YYYY-MM-DD. Must be ≥ from.
ParameterTypeDescription
limitnumberPage size. Default 500, max 5000. results_count is the size of this page, total_count the number of bars in the whole range; follow next_offset until it is null.
offsetnumberZero-based row offset applied after sort. Default 0.
sortstringSort bars by timestamp t before pagination. asc or desc (default desc).
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
}
  • Valid pairs: 1, 5, 15 / minute; 1, 4 / hour; 1 / day. Others return 400.
  • 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. vis 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.
  • results_count is page length; total_count is the whole range.
GET/perpetuals/agg/:symbol/prev

Previous completed daily bar

The most recently completed UTC daily candle for the contract.

ParameterTypeDescription
symbolreqstringPerpetual contract symbol (for example XAUUSDT, TSMUSDT, BTCUSDT). Trimmed and uppercased before lookup. Retrieve the full list from GET /perpetuals/symbols.
ParameterTypeDescription
intervalstringOptional. 1m · 5m · 15m · 1h · 4h · 1d. 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. Omit for the daily bar.
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. Pass ?interval= (1m, 5m, 15m, 1h, 4h, 1d) for the most recently settled bar at that interval instead; the response then also carries interval, bar_start, bar_end and as_of.

WebSocket

Three channels ride the same public stream, key and subscribe message as every other feed: perpetuals.quotes for the composite top of book, perpetuals.marks for the composite mark price and perpetuals.trades for executions across sources in arrival order. They are part of the Business plan. Frames follow the stream dialect: prices and sizes are strings and the event time is ts. Quotes and marks are conflated to the latest value ten times a second; a price change goes out on the next flush, while a size-only change waits up to 250 ms. Right after the subscribe acknowledgement the stream replays the last known quote and mark as frames marked snapshot: true, because a quiet contract can sit unchanged for a while and silence would be ambiguous; send snapshot: false to skip the replay. Trades never replay.
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 be enabled for source-level data: every quote, mark and trade per source, next to the composite, on the same routes and channels. A source row adds four fields: source_id, the identifier of the source; venue_symbol, the symbol on that source; native_currency, the currency it quotes in; and market_type, perpetual or spot. Without the add-on the request answers 403 source-level access not enabled for your account and the stream sends composite frames only. Talk to us.
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
}
The array holds 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. On the stream, perpetuals.marks carries venue_mark frames and every trade frame gains the four fields. Composite frames keep their quote and mark types, so a consumer of the composite can never mistake one source for it. Source rows are raw per-source values in their native currency; nothing is converted.