> From TickerLayer docs, Forex: https://tickerlayer.com/docs/products/forex#forex-agg-range
> REST base URL https://api.tickerlayer.com, API key in the `x-api-key` header. WebSocket wss://stream.tickerlayer.com?apiKey=YOUR_API_KEY. Full API reference: https://tickerlayer.com/llms-full.txt

## Aggregate bars (OHLCV)

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

Historical FX bars between two UTC calendar dates.

### 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/forex/agg/EURUSD/1/day/2025-11-01/2025-11-30?sort=desc&limit=2" \
  -H "x-api-key: <YOUR_API_KEY>"
```

```python
import requests

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

```javascript
const res = await fetch(
  "https://api.tickerlayer.com/forex/agg/EURUSD/1/day/2025-11-01/2025-11-30?sort=desc&limit=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/forex/agg/EURUSD/1/day/2025-11-01/2025-11-30?sort=desc&limit=2", nil)
req.Header.Set("x-api-key", "<YOUR_API_KEY>")
```

### Response

```json
{
  "symbol": "EURUSD",
  "results_count": 2,
  "results": [
    { "o": 1.0500, "h": 1.0528, "l": 1.0488, "c": 1.0523, "v": 9820000000, "t": 1733011200000 },
    { "o": 1.0475, "h": 1.0505, "l": 1.0460, "c": 1.0500, "v": 8750000000, "t": 1732924800000 }
  ],
  "next_offset": 2
}
```

### 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.
- `v` may occasionally be null when no consolidated volume is published for that interval.
