> TickerLayer documentation for AI agents and LLMs, the Markdown version of https://tickerlayer.com/docs/products/futures
> REST base URL https://api.tickerlayer.com, API key in the `x-api-key` header. WebSocket wss://stream.tickerlayer.com?apiKey=YOUR_API_KEY.
> Any docs page reads as Markdown at its URL plus `.md`. Index: https://tickerlayer.com/llms.txt · Full API reference: https://tickerlayer.com/llms-full.txt

# Futures CFDs

Contract months, the front-month chain and roll series for energy, metals, grains, rates and US equity indices, priced by our own methodology.

- **Auth:** x-api-key header
- **Base path:** /futures
- **WebSocket:** futures.quotes
- **Symbol format:** WTIUSD.DEC26, XAUUSD.C1, US500.R5

## How prices are built

A Futures CFD is a reference price that TickerLayer calculates with its own methodology for one contract month, one position of the front-month chain or one roll series of a listed futures market. The product and its methodology are on the [Futures CFDs product page](https://tickerlayer.com/data-assets/futures).

- **One price per month:** The bid is the median of the live input bids for that month and the ask the median of the live input asks, so the book is never crossed. price is the mid of the two, spread the gap between them.
- **`estimated`:** A month whose own book is empty or wider than 1% of its mid is never priced at that mid. A delivery month in its last days can quote a book like 3974 / 4536: real quotes, but no price to rely on. Such a month is carried from the nearest month of the same product that has a usable book, at the spread between the two the last time both had one (none when that was never seen), and kept inside its own bid and ask. It answers with `estimated: true`, `estimated_from` naming that month, `live: false` and that month’s `timestamp`; with no usable month in the product it answers `404 no price for this symbol`. The curve lists only months with a book of their own.
- **`live`:** `true` while a live input stands behind the price. When none does (the daily break, the weekend, a lost input) the last price is held with `live: false`. A far month that rarely trades can carry an old `timestamp`: read it, not only the flag.
- **`market_status`:** `open` or `closed` by the product’s session clock; `market_hours` on [GET /futures/products](https://tickerlayer.com/docs/products/futures#futures-products-route) states it per product. Gold 24/7 (`XAUUSD247`) trades around the clock, weekends included, apart from a two-hour break on Saturday.
- **Units:** As the market quotes the product, in `unit`: USD per barrel for crude oil, US cents per bushel for grains, points of par for Treasury notes, `100 minus the rate` for three-month SOFR, index points for equity indices. Prices are never converted.
- **Times:** `timestamp` is the event time of the price in epoch milliseconds. `transaction_time_us` is the same instant in microseconds, `ingress_time_us` when we received it and `publish_time_us` when the response or frame was built.
- **`volume`:** Contracts traded in the current session as our inputs saw them, reset when the trade date turns; null when none were seen. On a roll series it is the volume of the front month.

## Symbol forms

Every symbol starts with the product base, a plain name with no exchange code: `WTIUSD`, `XAUUSD`, `US500`, `UST5Y`. Three kinds follow the dot.

| Form | Example | What it prices |
| --- | --- | --- |
| `BASE.MMMYY` | `WTIUSD.DEC26` | One delivery month. Listed while we carry it: [GET /futures/contracts](https://tickerlayer.com/docs/products/futures#futures-contracts) returns the months. |
| `BASE.C1` | `XAUUSD.C2` | The chain: `C1`, `C2` and `C3` are the three nearest months of the product’s cycle (`chain_months`), raw prices, never adjusted. A month leaves `C1` when the session of its roll date opens, 18:00 New York the evening before, and every position moves up one. |
| `BASE.R5` | `US500.R5` | A roll series: one continuous price that moves from the front month to the next under one of four schedules, `R5`, `R5C`, `CYCLE` or `NOTICE`. See [Roll methods](https://tickerlayer.com/docs/products/futures#futures-rolls). |

Months outside the cycle, such as the serial gold months, are listed as dated months with `in_chain: false` but never enter the chain. `roll_date` is the trade date a month leaves the front of the chain; it equals the last trading day for every product. A trade date’s session runs from 18:00 New York the evening before to 17:00 New York on the day.

## Roll methods

Every roll series blends the chain front and the next month: bid, ask and price are each `(1 - weight) × front + weight × next`, where `weight` is the share of the next month, from 0 to 1. The four methods differ only in how the weight moves. All of them follow published calendar rules, so every step is known in advance on the [roll calendar](https://tickerlayer.com/docs/products/futures#futures-roll-calendar).

| Series | Weight of the next month |
| --- | --- |
| `.R5` | Five steps of 0.2 across the roll window, one at each window session close (17:00 New York). The window is business days 5 to 9 of the roll month on the US equity market calendar. The roll month is the month before delivery, or the month the contract stops trading when that is earlier, and a month earlier again when the window would not end before the last trading day. |
| `.R5C` | The same window, rising continuously through each window session instead of in steps, and flat between sessions. |
| `.CYCLE` | Spread over the whole cycle: weekdays elapsed since the previous front left the chain, over the weekdays between that date and this front’s roll date. It grows by 1/n each weekday. |
| `.NOTICE` | A hard switch: 0 before the session of the front’s `first_notice_date` (the last weekday of the month before the contract month), 1 from it. |

- **Roll fields:** A roll series answers the quote fields plus `method`, `weight`, `front` and `next` (the two months it blends), `front_price`, `next_price`, `front_estimated` and `next_estimated`; `.R5` and `.R5C` also carry `roll_window_start` and `roll_window_end`. `bid_size` and `ask_size` are `null`: a blend has no displayed size.
- **`next_estimated`:** true when the next month had no reliable live price and its leg was carried as the front plus the last spread seen while both months were live. Once the weight is 1, the series prices from the next month alone, so an expiring front without a usable book does not take it down.
- **`front_estimated`:** true when the front month had no usable book and its leg was carried from its nearest month that has one, as above. The series then has estimated: true while the front still carries weight.
- **At rotation:** When the chain rotates, the old next month becomes the front of every roll series and the weights start over for the new cycle.

**GET /futures/quote/US500.R5**

```json
{
  "symbol": "US500.R5",
  "kind": "roll",
  "base": "US500",
  "name": "US 500 index",
  "unit": "index points",
  "contract": "US500.DEC26",
  "contract_month": "2026-12",
  "rank": 1,
  "last_trade_date": "2026-12-18",
  "roll_date": "2026-12-18",
  "first_notice_date": "2026-11-30",
  "market_status": "open",
  "trading_day_of_month": 17,
  "trading_days_in_month": 22,
  "bid": 7668.75,
  "ask": 7669,
  "price": 7668.875,
  "spread": 0.25,
  "bid_size": null,
  "ask_size": null,
  "volume": 34204,
  "live": true,
  "estimated": false,
  "timestamp": 1792778642387,
  "transaction_time_us": 1792778642387000,
  "ingress_time_us": 1792778642624000,
  "publish_time_us": 1792778642646000,
  "method": "r5",
  "weight": 0,
  "front": "US500.DEC26",
  "next": "US500.MAR27",
  "front_price": 7668.875,
  "next_price": 7744,
  "front_estimated": false,
  "next_estimated": false,
  "roll_window_start": "2026-11-05T23:00:00.000Z",
  "roll_window_end": "2026-11-12T22:00:00.000Z"
}
```

**Roll fields on the front month (opt-in).** To read the chain front and its rolled prices in one answer, add `rolls`: `?rolls=r5,cycle` on REST, `"rolls": ["r5", "cycle"]` in a WebSocket subscribe. Accepted values are `r5`, `r5c`, `cycle`, `notice` and `all`. Every `.C1` in the answer gains a `rolls` object with `price`, `bid`, `ask` and `weight` per method; every other field stays as it was, and so does the payload of a request without the parameter. Any other value answers `400` on REST and `INVALID_ROLLS` on the stream.

**GET /futures/quote/WTIUSD.C1?rolls=r5,cycle**

```json
{
  "symbol": "WTIUSD.C1",
  "kind": "chain",
  "base": "WTIUSD",
  "name": "WTI crude oil",
  "unit": "USD per barrel",
  "contract": "WTIUSD.DEC26",
  "contract_month": "2026-12",
  "rank": 1,
  "last_trade_date": "2026-11-20",
  "roll_date": "2026-11-20",
  "first_notice_date": "2026-11-30",
  "market_status": "open",
  "trading_day_of_month": 17,
  "trading_days_in_month": 22,
  "bid": 102.99,
  "ask": 103.01,
  "price": 103,
  "spread": 0.02,
  "bid_size": 6,
  "ask_size": 5,
  "volume": 4464,
  "live": true,
  "estimated": false,
  "timestamp": 1792778642101,
  "transaction_time_us": 1792778642101000,
  "ingress_time_us": 1792778642342000,
  "publish_time_us": 1792778642467000,
  "rolls": {
    "r5": { "price": 103, "bid": 102.99, "ask": 103.01, "weight": 0 },
    "cycle": {
      "price": 102.68826087,
      "bid": 102.67826087,
      "ask": 102.69826087,
      "weight": 0.13043478260869565
    }
  }
}
```

## Products

20 products across energy, metals, agriculture, rates and US equity indices. Each name links to the product’s symbol page.

| Base | Product | Unit | Chain months |
| --- | --- | --- | --- |
| `WTIUSD` | [WTI crude oil](https://tickerlayer.com/symbols/wtiusd-futures) | USD per barrel | JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC |
| `BRENTUSD` | [Brent crude oil](https://tickerlayer.com/symbols/brentusd-futures) | USD per barrel | JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC |
| `NGASUSD` | [Natural gas](https://tickerlayer.com/symbols/ngasusd-futures) | USD per MMBtu | JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC |
| `XAUUSD` | [Gold](https://tickerlayer.com/symbols/xauusd-futures) | USD per troy ounce | FEB APR JUN AUG OCT DEC |
| `XAUUSD247` | [Gold 24/7](https://tickerlayer.com/symbols/xauusd247-futures) | USD per troy ounce | FEB APR JUN AUG OCT DEC |
| `XAGUSD` | [Silver](https://tickerlayer.com/symbols/xagusd-futures) | USD per troy ounce | MAR MAY JUL SEP DEC |
| `COPPERUSD` | [Copper](https://tickerlayer.com/symbols/copperusd-futures) | USD per pound | MAR MAY JUL SEP DEC |
| `ALUMINUMUSD` | [Aluminum](https://tickerlayer.com/symbols/aluminumusd-futures) | USD per metric ton | JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC |
| `XPDUSD` | [Palladium](https://tickerlayer.com/symbols/xpdusd-futures) | USD per troy ounce | MAR JUN SEP DEC |
| `CORNUSD` | [Corn](https://tickerlayer.com/symbols/cornusd-futures) | US cents per bushel | MAR MAY JUL SEP DEC |
| `WHEATUSD` | [Wheat](https://tickerlayer.com/symbols/wheatusd-futures) | US cents per bushel | MAR MAY JUL SEP DEC |
| `SOYBEANUSD` | [Soybeans](https://tickerlayer.com/symbols/soybeanusd-futures) | US cents per bushel | JAN MAR MAY JUL AUG SEP NOV |
| `LIVECATTLEUSD` | [Live cattle](https://tickerlayer.com/symbols/livecattleusd-futures) | US cents per pound | FEB APR JUN AUG OCT DEC |
| `UST2Y` | [US Treasury 2-year note](https://tickerlayer.com/symbols/ust2y-futures) | points of par | MAR JUN SEP DEC |
| `UST5Y` | [US Treasury 5-year note](https://tickerlayer.com/symbols/ust5y-futures) | points of par | MAR JUN SEP DEC |
| `UST30Y` | [US Treasury bond](https://tickerlayer.com/symbols/ust30y-futures) | points of par | MAR JUN SEP DEC |
| `SOFR3M` | [Three-month SOFR](https://tickerlayer.com/symbols/sofr3m-futures) | 100 minus the rate | MAR JUN SEP DEC |
| `US500` | [US 500 index](https://tickerlayer.com/symbols/us500-futures) | index points | MAR JUN SEP DEC |
| `US100` | [US Tech 100 index](https://tickerlayer.com/symbols/us100-futures) | index points | MAR JUN SEP DEC |
| `US2000` | [US Small Cap 2000 index](https://tickerlayer.com/symbols/us2000-futures) | index points | MAR JUN SEP DEC |

## Product list

**Endpoint:** `GET /futures/products`

Every product with its unit, chain months, session clock and the chain and roll symbols it answers. Open to any valid key, with or without Futures CFDs on the account.

### Request

```bash
curl -sS "https://api.tickerlayer.com/futures/products" \
  -H "x-api-key: <YOUR_API_KEY>"
```

```python
import requests

res = requests.get(
    "https://api.tickerlayer.com/futures/products",
    headers={"x-api-key": "<YOUR_API_KEY>"},
)
print(res.json())
```

```javascript
const res = await fetch("https://api.tickerlayer.com/futures/products", {
  headers: { "x-api-key": "<YOUR_API_KEY>" },
});
const data = await res.json();
console.log(data);
```

```go
req, _ := http.NewRequest("GET", "https://api.tickerlayer.com/futures/products", nil)
req.Header.Set("x-api-key", "<YOUR_API_KEY>")
```

### Response

```json
{
  "products": [
    {
      "base": "WTIUSD",
      "name": "WTI crude oil",
      "group": "energy",
      "unit": "USD per barrel",
      "chain_months": ["JAN", "FEB", "MAR", "APR", "MAY", "JUN",
                       "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"],
      "market_hours": "Sunday 18:00 to Friday 17:00 New York time, daily break 17:00 to 18:00",
      "chain": ["WTIUSD.C1", "WTIUSD.C2", "WTIUSD.C3"],
      "rolls": ["WTIUSD.R5", "WTIUSD.R5C", "WTIUSD.CYCLE", "WTIUSD.NOTICE"],
      "contracts": 32
    }
  ],
  "count": 20
}
```

### Notes

`group` is `energy`, `metals`, `agriculture`, `rates` or `indices`. `contracts` is how many dated months we carry now. A product with no month carried is left out of the list.

## Contract months

**Endpoint:** `GET /futures/contracts`

Every dated month we carry, with its place in the chain and its calendar: last trading day, roll date, first notice date and roll window. Open to any valid key.

### Query parameters

| Parameter | Type | Description |
| --- | --- | --- |
| `base` | string | One product, for example US500. Leave it out for every product. |

### Request

```bash
curl -sS "https://api.tickerlayer.com/futures/contracts?base=US500" \
  -H "x-api-key: <YOUR_API_KEY>"
```

```python
import requests

res = requests.get(
    "https://api.tickerlayer.com/futures/contracts?base=US500",
    headers={"x-api-key": "<YOUR_API_KEY>"},
)
print(res.json())
```

```javascript
const res = await fetch("https://api.tickerlayer.com/futures/contracts?base=US500", {
  headers: { "x-api-key": "<YOUR_API_KEY>" },
});
const data = await res.json();
console.log(data);
```

```go
req, _ := http.NewRequest("GET", "https://api.tickerlayer.com/futures/contracts?base=US500", nil)
req.Header.Set("x-api-key", "<YOUR_API_KEY>")
```

### Response

```json
{
  "contracts": [
    {
      "symbol": "US500.DEC26",
      "base": "US500",
      "contract_month": "2026-12",
      "rank": 1,
      "in_chain": true,
      "last_trade_date": "2026-12-18",
      "roll_date": "2026-12-18",
      "first_notice_date": "2026-11-30",
      "roll_window_start": "2026-11-05T23:00:00.000Z",
      "roll_window_end": "2026-11-12T22:00:00.000Z",
      "days_to_expiry": 56,
      "market_status": "open"
    },
    {
      "symbol": "US500.SEP27",
      "base": "US500",
      "contract_month": "2027-09",
      "rank": null,
      "in_chain": true,
      "last_trade_date": "2027-09-17",
      "roll_date": "2027-09-17",
      "first_notice_date": "2027-08-31",
      "roll_window_start": "2027-08-05T22:00:00.000Z",
      "roll_window_end": "2027-08-12T21:00:00.000Z",
      "days_to_expiry": 329,
      "market_status": "open"
    }
  ],
  "count": 5
}
```

### Notes

`rank` is the month’s chain position (1 is `C1`), or `null` beyond `C3` or outside the cycle. Dates are UTC calendar days; `roll_window_start` and `roll_window_end` are the open of the first window session and the close of the last. `days_to_expiry` counts calendar days from the current trade date to the last trading day. An unknown base answers `404 unknown futures product`.

## Roll calendar

**Endpoint:** `GET /futures/roll-calendar/:base`

Every chain rotation and roll window of a product, from the current one on. Open to any valid key.

### Path parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `base` | string | Yes | Product base, for example WTIUSD, XAUUSD or UST5Y. GET /futures/products lists them. |

### Query parameters

| Parameter | Type | Description |
| --- | --- | --- |
| `months` | integer | How far ahead to list, from 1 to 36 months. Default 12. |

### Request

```bash
curl -sS "https://api.tickerlayer.com/futures/roll-calendar/WTIUSD?months=2" \
  -H "x-api-key: <YOUR_API_KEY>"
```

```python
import requests

res = requests.get(
    "https://api.tickerlayer.com/futures/roll-calendar/WTIUSD?months=2",
    headers={"x-api-key": "<YOUR_API_KEY>"},
)
print(res.json())
```

```javascript
const res = await fetch("https://api.tickerlayer.com/futures/roll-calendar/WTIUSD?months=2", {
  headers: { "x-api-key": "<YOUR_API_KEY>" },
});
const data = await res.json();
console.log(data);
```

```go
req, _ := http.NewRequest("GET", "https://api.tickerlayer.com/futures/roll-calendar/WTIUSD?months=2", nil)
req.Header.Set("x-api-key", "<YOUR_API_KEY>")
```

### Response

```json
{
  "base": "WTIUSD",
  "name": "WTI crude oil",
  "rolls": [
    {
      "front": "WTIUSD.DEC26",
      "next": "WTIUSD.JAN27",
      "roll_window_start": "2026-11-05T23:00:00.000Z",
      "roll_window_end": "2026-11-12T22:00:00.000Z",
      "roll_window_days": ["2026-11-06", "2026-11-09", "2026-11-10",
                           "2026-11-11", "2026-11-12"],
      "cycle_start": "2026-10-19T22:00:00.000Z",
      "first_notice_date": "2026-11-30",
      "last_trade_date": "2026-11-20",
      "rotation_at": "2026-11-19T23:00:00.000Z"
    },
    {
      "front": "WTIUSD.JAN27",
      "next": "WTIUSD.FEB27",
      "roll_window_start": "2026-12-06T23:00:00.000Z",
      "roll_window_end": "2026-12-11T22:00:00.000Z",
      "roll_window_days": ["2026-12-07", "2026-12-08", "2026-12-09",
                           "2026-12-10", "2026-12-11"],
      "cycle_start": "2026-11-19T23:00:00.000Z",
      "first_notice_date": "2026-12-31",
      "last_trade_date": "2026-12-21",
      "rotation_at": "2026-12-20T23:00:00.000Z"
    }
  ]
}
```

### Notes

`roll_window_days` are the five trade dates the `.R5` and `.R5C` weights move on. `cycle_start` is when the `.CYCLE` weight of this front starts counting, and `rotation_at` when `C1` moves to `next`. A `months` value outside 1 to 36 answers `400 months must be a whole number from 1 to 36`.

## Latest quote

**Endpoint:** `GET /futures/quote/:symbol`

The price of one contract month, chain position or roll series, with its calendar fields.

### Path parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `symbol` | string | Yes | A contract month (WTIUSD.DEC26), a chain position (XAUUSD.C1 to .C3) or a roll series (US500.R5, .R5C, .CYCLE, .NOTICE). Trimmed and uppercased before lookup. |

### Query parameters

| Parameter | Type | Description |
| --- | --- | --- |
| `rolls` | string | Opt-in. Comma-separated roll methods to add to every chain front (.C1) in the answer: r5, r5c, cycle, notice, or all. Other symbols are unchanged. Leave it out for the default payload. |

### Request

```bash
curl -sS "https://api.tickerlayer.com/futures/quote/XAUUSD.C2" \
  -H "x-api-key: <YOUR_API_KEY>"
```

```python
import requests

res = requests.get(
    "https://api.tickerlayer.com/futures/quote/XAUUSD.C2",
    headers={"x-api-key": "<YOUR_API_KEY>"},
)
print(res.json())
```

```javascript
const res = await fetch("https://api.tickerlayer.com/futures/quote/XAUUSD.C2", {
  headers: { "x-api-key": "<YOUR_API_KEY>" },
});
const data = await res.json();
console.log(data);
```

```go
req, _ := http.NewRequest("GET", "https://api.tickerlayer.com/futures/quote/XAUUSD.C2", nil)
req.Header.Set("x-api-key", "<YOUR_API_KEY>")
```

### Response

```json
{
  "symbol": "XAUUSD.C2",
  "kind": "chain",
  "base": "XAUUSD",
  "name": "Gold",
  "unit": "USD per troy ounce",
  "contract": "XAUUSD.DEC26",
  "contract_month": "2026-12",
  "rank": 2,
  "last_trade_date": "2026-12-29",
  "roll_date": "2026-12-29",
  "first_notice_date": "2026-11-30",
  "market_status": "open",
  "trading_day_of_month": 17,
  "trading_days_in_month": 22,
  "bid": 4012.8,
  "ask": 4013.1,
  "price": 4012.95,
  "spread": 0.3,
  "bid_size": 1,
  "ask_size": 2,
  "volume": 839,
  "live": true,
  "estimated": false,
  "timestamp": 1792778642388,
  "transaction_time_us": 1792778642388000,
  "ingress_time_us": 1792778642624000,
  "publish_time_us": 1792778642819000
}
```

### Notes

`kind` is `contract`, `chain` or `roll`. `contract` is the dated month the price is on (for a roll series, the front month) and `rank` its chain position. `trading_day_of_month` is the current trade date’s place among the month’s US business days (0 on a day that is not one), out of `trading_days_in_month`. `403 futures access not enabled for your account`: the account does not include Futures CFDs. `404 unknown symbol`: the base or the symbol form is not one we list. `404 no price for this symbol`: the product is known, but the month is not carried, or no month of the product has a usable book yet.

## Several quotes

**Endpoint:** `GET /futures/quotes`

Up to 50 symbols of any form and any product in one request.

### Query parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `symbols` | string | Yes | Comma-separated futures symbols, 1 to 50. Duplicates count once. |
| `rolls` | string | No | Opt-in. Comma-separated roll methods to add to every chain front (.C1) in the answer: r5, r5c, cycle, notice, or all. Other symbols are unchanged. Leave it out for the default payload. |

### Request

```bash
curl -sS "https://api.tickerlayer.com/futures/quotes?symbols=BRENTUSD.C1,UST5Y.C1,WTIUSD.MAR30" \
  -H "x-api-key: <YOUR_API_KEY>"
```

```python
import requests

res = requests.get(
    "https://api.tickerlayer.com/futures/quotes?symbols=BRENTUSD.C1,UST5Y.C1,WTIUSD.MAR30",
    headers={"x-api-key": "<YOUR_API_KEY>"},
)
print(res.json())
```

```javascript
const res = await fetch("https://api.tickerlayer.com/futures/quotes?symbols=BRENTUSD.C1,UST5Y.C1,WTIUSD.MAR30", {
  headers: { "x-api-key": "<YOUR_API_KEY>" },
});
const data = await res.json();
console.log(data);
```

```go
req, _ := http.NewRequest("GET", "https://api.tickerlayer.com/futures/quotes?symbols=BRENTUSD.C1,UST5Y.C1,WTIUSD.MAR30", nil)
req.Header.Set("x-api-key", "<YOUR_API_KEY>")
```

### Response

```json
{
  "quotes": [
    {
      "symbol": "BRENTUSD.C1",
      "kind": "chain",
      "base": "BRENTUSD",
      "name": "Brent crude oil",
      "unit": "USD per barrel",
      "contract": "BRENTUSD.DEC26",
      "contract_month": "2026-12",
      "rank": 1,
      "last_trade_date": "2026-10-30",
      "roll_date": "2026-10-30",
      "first_notice_date": "2026-11-30",
      "market_status": "open",
      "trading_day_of_month": 17,
      "trading_days_in_month": 22,
      "bid": 116.38,
      "ask": 116.41,
      "price": 116.395,
      "spread": 0.03,
      "bid_size": 1,
      "ask_size": 2,
      "volume": 330,
      "live": true,
      "estimated": false,
      "timestamp": 1792778642473,
      "transaction_time_us": 1792778642473000,
      "ingress_time_us": 1792778642707000,
      "publish_time_us": 1792778642819000
    },
    {
      "symbol": "UST5Y.C1",
      "kind": "chain",
      "base": "UST5Y",
      "name": "US Treasury 5-year note",
      "unit": "points of par",
      "contract": "UST5Y.DEC26",
      "contract_month": "2026-12",
      "rank": 1,
      "last_trade_date": "2026-12-31",
      "roll_date": "2026-12-31",
      "first_notice_date": "2026-11-30",
      "market_status": "open",
      "trading_day_of_month": 17,
      "trading_days_in_month": 22,
      "bid": 104.5,
      "ask": 104.50781,
      "price": 104.503905,
      "spread": 0.00781,
      "bid_size": 1765,
      "ask_size": 1745,
      "volume": 30213,
      "live": true,
      "estimated": false,
      "timestamp": 1792778642485,
      "transaction_time_us": 1792778642485000,
      "ingress_time_us": 1792778642725000,
      "publish_time_us": 1792778642819000
    }
  ],
  "missing": ["WTIUSD.MAR30"],
  "count": 2
}
```

### Notes

A symbol without a price, for any of the reasons a single quote answers `404`, is listed in `missing` instead of failing the request. An empty list or more than 50 symbols answers `400 symbols must list 1 to 50 futures symbols, comma separated`.

## Curve

**Endpoint:** `GET /futures/curve/:base`

Every priced month of a product, nearest first, with the annualized carry between neighbours.

### Path parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `base` | string | Yes | Product base, for example WTIUSD, XAUUSD or UST5Y. GET /futures/products lists them. |

### Request

```bash
curl -sS "https://api.tickerlayer.com/futures/curve/WTIUSD" \
  -H "x-api-key: <YOUR_API_KEY>"
```

```python
import requests

res = requests.get(
    "https://api.tickerlayer.com/futures/curve/WTIUSD",
    headers={"x-api-key": "<YOUR_API_KEY>"},
)
print(res.json())
```

```javascript
const res = await fetch("https://api.tickerlayer.com/futures/curve/WTIUSD", {
  headers: { "x-api-key": "<YOUR_API_KEY>" },
});
const data = await res.json();
console.log(data);
```

```go
req, _ := http.NewRequest("GET", "https://api.tickerlayer.com/futures/curve/WTIUSD", nil)
req.Header.Set("x-api-key", "<YOUR_API_KEY>")
```

### Response

```json
{
  "base": "WTIUSD",
  "name": "WTI crude oil",
  "unit": "USD per barrel",
  "market_status": "open",
  "months": [
    {
      "symbol": "WTIUSD.DEC26",
      "contract_month": "2026-12",
      "rank": 1,
      "last_trade_date": "2026-11-20",
      "days_to_expiry": 28,
      "bid": 103.01,
      "ask": 103.02,
      "price": 103.015,
      "volume": 4497,
      "live": true,
      "timestamp": 1792778652220,
      "carry_annualized": null
    },
    {
      "symbol": "WTIUSD.JAN27",
      "contract_month": "2027-01",
      "rank": 2,
      "last_trade_date": "2026-12-21",
      "days_to_expiry": 59,
      "bid": 100.61,
      "ask": 100.63,
      "price": 100.62,
      "volume": 988,
      "live": true,
      "timestamp": 1792778652221,
      "carry_annualized": -0.276971
    }
  ],
  "count": 22,
  "timestamp": 1792778652528
}
```

### Notes

`carry_annualized` is the log change of `price` from the previous month, divided by the years between their last trading days: negative when the curve slopes down (backwardation), positive when it slopes up (contango). It is `null` on the first month and on three-month SOFR, which is quoted as 100 minus a rate. A month without a price is left out. The top-level `timestamp` is when the curve was read. `403` and `404 unknown futures product` as above.

## WebSocket

One channel, `futures.quotes`, on the same stream, key and subscribe message as every other feed, for accounts with Futures CFDs. Subscribe to any mix of dated months, chain positions and roll series. Frames follow the stream dialect: prices and sizes are strings and the event time is `ts`.

- **`seq`:** A sequence number per symbol that rises with each update the stream sends for it. Frames of the same update carry the same number, whatever options a connection chose.
- **Snapshot:** Right after the subscribe, the last price of each symbol is replayed with `snapshot: true` and the current `seq`, however old it is: a held price is still the price. Send `snapshot: false` to skip it.
- **Roll series:** A roll series updates when either of its months does. While a roll window session is open, `.R5C`, and `.C1` on connections that asked for roll fields, are also re-sent every second, because the continuous weight moves by itself. The `rolls` option adds the roll fields to every `.C1` frame; the latest futures subscribe on a connection sets it for the connection.
- **Rejections:** A dated month we do not carry is rejected with `INVALID_SYMBOL` and the hint `This contract month is not listed. Use GET /futures/contracts for the listed months.` Without Futures CFDs on the account, symbols are rejected with `UNAUTHORIZED_SYMBOL`.

**Subscribe**

```json
{
  "action": "subscribe",
  "channels": ["futures.quotes"],
  "symbols": ["WTIUSD.C1", "XAUUSD.DEC26", "US500.R5"],
  "rolls": ["r5", "cycle"]
}
```

**quote frame, chain front with roll fields**

```json
{
  "type": "quote",
  "channel": "futures.quotes",
  "asset": "futures",
  "symbol": "WTIUSD.C1",
  "kind": "chain",
  "contract": "WTIUSD.DEC26",
  "contract_month": "2026-12",
  "rank": 1,
  "bid": "102.99",
  "ask": "103.01",
  "price": "103",
  "spread": "0.02",
  "bid_size": "6",
  "ask_size": "5",
  "volume": "4464",
  "live": true,
  "estimated": false,
  "market_status": "open",
  "last_trade_date": "2026-11-20",
  "roll_date": "2026-11-20",
  "first_notice_date": "2026-11-30",
  "trading_day_of_month": 17,
  "trading_days_in_month": 22,
  "seq": 1842,
  "ts": 1792778642101,
  "transaction_time_us": 1792778642101000,
  "ingress_time_us": 1792778642342000,
  "publish_time_us": 1792778642467000,
  "rolls": {
    "r5": { "price": "103", "bid": "102.99", "ask": "103.01", "weight": 0 },
    "cycle": { "price": "102.68826087", "bid": "102.67826087", "ask": "102.69826087", "weight": 0.13043478260869565 }
  }
}
```

**quote frame, roll series**

```json
{
  "type": "quote",
  "channel": "futures.quotes",
  "asset": "futures",
  "symbol": "US500.R5",
  "kind": "roll",
  "contract": "US500.DEC26",
  "contract_month": "2026-12",
  "rank": 1,
  "bid": "7668.75",
  "ask": "7669",
  "price": "7668.875",
  "spread": "0.25",
  "bid_size": null,
  "ask_size": null,
  "volume": "34204",
  "live": true,
  "estimated": false,
  "market_status": "open",
  "last_trade_date": "2026-12-18",
  "roll_date": "2026-12-18",
  "first_notice_date": "2026-11-30",
  "trading_day_of_month": 17,
  "trading_days_in_month": 22,
  "seq": 917,
  "ts": 1792778642387,
  "transaction_time_us": 1792778642387000,
  "ingress_time_us": 1792778642624000,
  "publish_time_us": 1792778642646000,
  "method": "r5",
  "weight": 0,
  "front": "US500.DEC26",
  "next": "US500.MAR27",
  "front_price": "7668.875",
  "next_price": "7744",
  "front_estimated": false,
  "next_estimated": false,
  "roll_window_start": "2026-11-05T23:00:00.000Z",
  "roll_window_end": "2026-11-12T22:00:00.000Z"
}
```

Frames carry the same values as [GET /futures/quote](https://tickerlayer.com/docs/products/futures#futures-quote), without `base`, `name` and `unit`, which do not change: read them once from [GET /futures/products](https://tickerlayer.com/docs/products/futures#futures-products-route). `weight` stays a number.

## Before you use Futures CFDs

Futures CFDs are reference prices that TickerLayer calculates with its own methodology, one per contract month, chain position or roll series. They are not futures contracts, not executable, and not the official settlement, closing or index price of any market. TickerLayer publishes data only: it does not list, offer, broker or clear any contract, and it is not affiliated with, sponsored or endorsed by any trading venue, index provider or benchmark administrator.

The full text is in the [market data disclaimer](https://tickerlayer.com/market-data-disclaimer#futures). Coverage, roll methods and use cases are on the [Futures CFDs product page](https://tickerlayer.com/data-assets/futures).
