> From TickerLayer docs, Commodities: https://tickerlayer.com/docs/products/commodities#commodities-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 /commodities/agg/:symbol/:multiplier/:timespan/:from/:to`

Historical bars between two UTC calendar dates.

### Path parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `symbol` | string | Yes | Enabled commodity symbol (e.g. XAUUSD, CORNUSD). Trimmed and uppercased 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/commodities/agg/XAUUSD/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/commodities/agg/XAUUSD/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/commodities/agg/XAUUSD/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/commodities/agg/XAUUSD/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": "XAUUSD",
  "results_count": 2,
  "results": [
    { "o": 2295.10, "h": 2325.40, "l": 2288.20, "c": 2318.42, "v": 0, "t": 1733011200000 },
    { "o": 2270.50, "h": 2305.00, "l": 2265.00, "c": 2295.10, "v": 0, "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` is the aggregated volume for the bar. For energy, copper and the agricultural contracts it is the front-month futures contract's exchange volume over the bar's span; for the metals it comes from the aggregation layer. It is `null` when no volume is available for that bar, and `0` when the bar traded nothing.
