> TickerLayer documentation for AI agents and LLMs, the Markdown version of https://tickerlayer.com/docs/products/crypto
> 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

# Crypto

Spot-style crypto against USD (and similar) using compact symbols such as BTCUSD.

- **Auth:** x-api-key header
- **Base path:** /crypto
- **WebSocket:** crypto.quotes · crypto.trades
- **Symbol format:** Compact pairs (e.g. BTCUSD, ETHUSD)

Quotes and trades come from the aggregated, normalized spot view. Individual fields may be optional depending on market conditions; see each route for response details.

## Symbols

Symbols are compact pairs such as `BTCUSD` and `ETHUSD`. List enabled symbols with `GET /crypto/symbols` (see [Symbols → Crypto](https://tickerlayer.com/docs/rest/symbols#crypto-lists)).

## Symbol list

**Endpoint:** `GET /crypto/symbols`

Returns enabled crypto spot symbols with display names and a "crypto" type discriminator; sorted for stable discovery.

### Request

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

```python
import requests

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

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

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

### Response

```json
{
  "data": [
    { "symbol": "BTCUSD", "name": "Bitcoin / USD", "type": "crypto" },
    { "symbol": "ETHUSD", "name": "Ethereum / USD", "type": "crypto" }
  ],
  "count": 2
}
```

### Notes

Legacy `GET /symbols` merges crypto, forex, commodities, ETFs, and indices, not stocks. Prefer `GET /crypto/symbols` for crypto-only discovery.

## Latest quote

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

Best bid and ask with sizes from the latest normalized book snapshot for the symbol.

### Path parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `symbol` | string | Yes | Enabled crypto symbol (e.g. BTCUSD). Trimmed and uppercased before lookup. Retrieve the full list from GET /crypto/symbols. |

### Request

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

```python
import requests

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

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

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

### Response

```json
{
  "symbol": "BTCUSD",
  "bid": 84210.12,
  "ask": 84210.45,
  "bid_size": 1.2,
  "ask_size": 0.8,
  "timestamp": 1743512400000
}
```

### Notes

`404 unknown symbol`: symbol not in the enabled registry. `404 no quote available`: cache has no quote yet for this symbol.

## Last trade

**Endpoint:** `GET /crypto/trade/last/:symbol`

Most recent executed trade price and size from the in-memory trade cache.

### Path parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `symbol` | string | Yes | Enabled crypto symbol (e.g. BTCUSD). Trimmed and uppercased before lookup. Retrieve the full list from GET /crypto/symbols. |

### Request

```bash
curl -sS "https://api.tickerlayer.com/crypto/trade/last/BTCUSD" \
  -H "x-api-key: <YOUR_API_KEY>"
```

```python
import requests

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

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

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

### Response

```json
{
  "symbol": "BTCUSD",
  "price": 84215.42,
  "size": 0.53,
  "timestamp": 1743512400000
}
```

### Notes

Returns `404 no trade available` when no consolidated trade exists yet for that symbol.

## Snapshot

**Endpoint:** `GET /crypto/snapshot/:symbol`

Combined view: latest bid/ask, last trade, previous daily close, and derived change metrics in one normalized aggregated snapshot. Missing pieces return as null; an all-null snapshot returns 404.

### Path parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `symbol` | string | Yes | Enabled crypto symbol (e.g. BTCUSD). Trimmed and uppercased before lookup. Retrieve the full list from GET /crypto/symbols. |

### Request

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

```python
import requests

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

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

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

### Response

```json
{
  "symbol": "BTCUSD",
  "bid": 84210.12,
  "ask": 84210.45,
  "bid_size": 1.2,
  "ask_size": 0.8,
  "last_price": 84215.42,
  "last_size": 0.53,
  "last_timestamp": 1743512400000,
  "prev_close": 83800.10,
  "change": 415.32,
  "change_percent": 0.4956
}
```

### Notes

- `change` and `change_percent` use last trade vs previous close; either may be `null` when inputs are not available in the aggregated view.
- If `prev_close` is `0`, `change_percent` is `null` to avoid division by zero.

## Previous bar

**Endpoint:** `GET /crypto/agg/:symbol/prev`

Single most-recently completed UTC daily candle for the symbol from the aggregated daily interval pipeline.

### Path parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `symbol` | string | Yes | Enabled crypto symbol (e.g. BTCUSD). Trimmed and uppercased before lookup. Retrieve the full list from GET /crypto/symbols. |

### Query parameters

| Parameter | Type | Description |
| --- | --- | --- |
| `interval` | string | 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. Values: `1m`, `5m`, `15m`, `1h`, `4h`, `1d`. |

### Request

```bash
curl -sS "https://api.tickerlayer.com/crypto/agg/BTCUSD/prev" \
  -H "x-api-key: <YOUR_API_KEY>"
```

```python
import requests

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

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

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

### Response

```json
{
  "symbol": "BTCUSD",
  "result": {
    "o": 83100,
    "h": 84200,
    "l": 82950,
    "c": 83800.10,
    "v": 1200.5,
    "t": 1730419200000
  }
}
```

### Notes

`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. While the market is closed the last real bar is returned, still labelled with its own `bar_start`.

## Aggregate bars (OHLCV)

**Endpoint:** `GET /crypto/agg/:symbol/:multiplier/:timespan/:from/:to`

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

### Path parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `symbol` | string | Yes | An enabled symbol of this asset class, for example `BTCUSD` or `US:KO`. Trimmed before lookup. |
| `multiplier` | number | Yes | 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. |
| `timespan` | string | Yes | Case-insensitive. Other values return `400`. Values: `minute`, `hour`, `day`. |
| `from` | string | Yes | First UTC date, inclusive, as `YYYY-MM-DD`. |
| `to` | string | Yes | Last UTC date, inclusive, as `YYYY-MM-DD`. Not before `from`. |

### Query parameters

| Parameter | Type | Description |
| --- | --- | --- |
| `limit` | number | 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`. Default: `500`. |
| `offset` | number | Zero-based row offset, applied after sorting. Default: `0`. |
| `sort` | string | Order of bars by timestamp `t`, applied before pagination. Values: `asc`, `desc`. Default: `desc`. |

### Request

```bash
curl -sS "https://api.tickerlayer.com/crypto/agg/BTCUSD/1/day/2025-11-01/2025-11-30?sort=desc&limit=3" \
  -H "x-api-key: <YOUR_API_KEY>"
```

```python
import requests

res = requests.get(
    "https://api.tickerlayer.com/crypto/agg/BTCUSD/1/day/2025-11-01/2025-11-30",
    params={"sort": "desc", "limit": 3},
    headers={"x-api-key": "<YOUR_API_KEY>"},
)
print(res.json())
```

```javascript
const res = await fetch(
  "https://api.tickerlayer.com/crypto/agg/BTCUSD/1/day/2025-11-01/2025-11-30?sort=desc&limit=3",
  { headers: { "x-api-key": "<YOUR_API_KEY>" } },
);
const data = await res.json();
console.log(data);
```

```go
req, _ := http.NewRequest("GET",
  "https://api.tickerlayer.com/crypto/agg/BTCUSD/1/day/2025-11-01/2025-11-30?sort=desc&limit=3", nil)
req.Header.Set("x-api-key", "<YOUR_API_KEY>")
```

### Response

```json
{
  "symbol": "BTCUSD",
  "results_count": 3,
  "results": [
    { "o": 83100, "h": 84200, "l": 82950, "c": 83800.10, "v": 1200.5, "t": 1730419200000 },
    { "o": 82500, "h": 83200, "l": 82100, "c": 83100,    "v": 980.2,  "t": 1730332800000 },
    { "o": 81900, "h": 82700, "l": 81500, "c": 82500,    "v": 1100.8, "t": 1730246400000 }
  ],
  "next_offset": 3
}
```

### Notes

- One request covers at most 31 days of 1-minute bars, 90 of 5-minute, 180 of 15-minute, 365 of hourly, 730 of 4-hour and 5000 of daily bars, counting `from` and `to` as whole UTC days. A longer range returns `400` with the limit in the message.

## WebSocket

Stream live quotes and trades for this asset class over the public WebSocket.

**Connect**

```
wss://stream.tickerlayer.com/?apiKey=<YOUR_API_KEY>
```

### Available channels

- `crypto.quotes`: quotes
- `crypto.trades`: trades

### Subscribe example

After the connection is ready, send a JSON text frame:

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

### Example messages

**crypto.quotes**

```json
{
  "type": "quote",
  "channel": "crypto.quotes",
  "asset": "crypto",
  "symbol": "BTCUSD",
  "bid": "84210.12",
  "ask": "84210.45",
  "bid_size": "1.2",
  "ask_size": "0.8",
  "ts": 1743512400000
}
```

**crypto.trades**

```json
{
  "type": "trade",
  "channel": "crypto.trades",
  "asset": "crypto",
  "symbol": "BTCUSD",
  "price": "84210.30",
  "size": "0.15",
  "ts": 1743512400000
}
```

`crypto.trades` is a **consolidated tape**: every execution from every venue we aggregate is delivered, in arrival order. Summing `size` over a window therefore gives you real consolidated volume for that window.

`size` is the raw executed base-asset amount for that single trade, exactly as the venue reported it, with no rounding and no normalisation. Two executions may legitimately carry the same price, size and timestamp; they are distinct trades and both are delivered.

### General WebSocket documentation

For authentication, subscribe/unsubscribe lifecycle, errors, limits, and heartbeats, see the [WebSocket overview](https://tickerlayer.com/docs/websocket), [Subscriptions](https://tickerlayer.com/docs/websocket/subscriptions) and [Message types](https://tickerlayer.com/docs/websocket/messages).
