# POST /v1/prices/history

Continuously updated OHLC price history for CS2 items since December 24, 2025.

Returns high-frequency OHLC (open, high, low, close) price history aggregated from the same snapshots as [latest prices](/docs/prices-latest). Historical coverage begins December 24, 2025. Each request accepts up to 100 items.

Items with Doppler, Gamma Doppler, or Case Hardened history can include `variants`.

## Access

Requires a Scale or Enterprise API key.

## Supported intervals

| Interval | Max range |
| --- | --- |
| `5m` | 14 days |
| `30m` | 90 days |
| `1h` | 365 days |
| `1d` | Unlimited |

## Supported sources

| Source | Fields |
| --- | --- |
| `buff` | `ask`, `bid`, `ask_volume`, `bid_volume` |
| `youpin` | `ask`, `bid`, `ask_volume`, `bid_volume` |
| `csfloat` | `ask`, `bid`, `ask_volume` |
| `skinport` | `ask`, `ask_volume` |
| `steam` | `ask`, `bid`, `ask_volume`, `bid_volume` |
| `c5game` | `ask`, `bid`, `ask_volume` |

By default, all sources are returned.

`bucket` is the UTC interval boundary. `open_time` and `close_time` are the actual first and last observations inside the bucket; see [Using the API](/docs/using-the-api#historical-response-buckets).

## Request

`POST https://api.cs2.sh/v1/prices/history`

**curl**

```bash
curl -X POST https://api.cs2.sh/v1/prices/history \
  -H "Authorization: Bearer <<YOUR_API_KEY>>" \
  -H "Accept-Encoding: gzip" --compressed \
  -H "Content-Type: application/json" \
  -d '{
  "items": [
    "USP-S | Printstream (Factory New)"
  ],
  "start": "2026-07-20",
  "end": "2026-07-23",
  "sources": [
    "buff",
    "csfloat"
  ],
  "interval": "1h"
}'
```

**Python**

```python
import requests

headers = {
    "Authorization": "Bearer <<YOUR_API_KEY>>",
    "Accept-Encoding": "gzip",
    "Content-Type": "application/json",
}

payload = {
    "items": ["USP-S | Printstream (Factory New)"],
    "start": "2026-07-20",
    "end": "2026-07-23",
    "sources": ["buff", "csfloat"],
    "interval": "1h",
}

response = requests.post(
    "https://api.cs2.sh/v1/prices/history",
    headers=headers,
    json=payload,
)

response.raise_for_status()
data = response.json()
```

**Node**

```javascript
const headers = {
  "Authorization": "Bearer <<YOUR_API_KEY>>",
  "Accept-Encoding": "gzip",
  "Content-Type": "application/json",
};

const response = await fetch("https://api.cs2.sh/v1/prices/history", {
  method: "POST",
  headers,
  body: JSON.stringify({
    "items": [
      "USP-S | Printstream (Factory New)"
    ],
    "start": "2026-07-20",
    "end": "2026-07-23",
    "sources": [
      "buff",
      "csfloat"
    ],
    "interval": "1h"
  }),
});

if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
```

**Go**

```go
package main

import (
    "bytes"
    "compress/gzip"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

func main() {
    payload := map[string]any{
        "items": []any{
            "USP-S | Printstream (Factory New)",
        },
        "start": "2026-07-20",
        "end": "2026-07-23",
        "sources": []any{
            "buff",
            "csfloat",
        },
        "interval": "1h",
    }
    body, _ := json.Marshal(payload)
    req, _ := http.NewRequest("POST", "https://api.cs2.sh/v1/prices/history", bytes.NewReader(body))
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Authorization", "Bearer <<YOUR_API_KEY>>")
    req.Header.Set("Accept-Encoding", "gzip")

    resp, err := http.DefaultClient.Do(req)
    if err != nil { panic(err) }
    defer resp.Body.Close()

    if resp.StatusCode < 200 || resp.StatusCode >= 300 {
        body, _ := io.ReadAll(resp.Body)
        panic(fmt.Sprintf("HTTP %d: %s", resp.StatusCode, body))
    }

    var reader io.Reader = resp.Body
    if resp.Header.Get("Content-Encoding") == "gzip" {
        gz, err := gzip.NewReader(resp.Body)
        if err != nil { panic(err) }
        defer gz.Close()
        reader = gz
    }

    var data any
    if err := json.NewDecoder(reader).Decode(&data); err != nil { panic(err) }
    fmt.Printf("%#v\n", data)
}
```

**R**

```r
library(httr2)

payload <- list(
  items = list(
    "USP-S | Printstream (Factory New)"
  ),
  start = "2026-07-20",
  end = "2026-07-23",
  sources = list(
    "buff",
    "csfloat"
  ),
  interval = "1h"
)

resp <- request("https://api.cs2.sh/v1/prices/history") |>
  req_headers(
    Authorization = "Bearer <<YOUR_API_KEY>>",
    `Accept-Encoding` = "gzip"
  ) |>
  req_body_json(payload) |>
  req_perform()

data <- resp_body_json(resp)
```

## Parameters

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `string[]` | Yes | List of market_hash_name values (max 100) |
| `start` | `string` | Yes | Start date (YYYY-MM-DD or RFC3339) |
| `end` | `string` | No | End date (YYYY-MM-DD or RFC3339). Default: now |
| `sources` | `string[]` | No | Filter to specific sources. Default: all sources |
| `interval` | `string` | No | Default: `5m`. Allowed: `5m`, `30m`, `1h`, `1d`. Aggregation interval |

## Response

```json
{
  "response_time": "2026-07-26T18:54:17.003186292Z",
  "currency": "USD",
  "start": "2026-07-20T00:00:00Z",
  "end": "2026-07-23T00:00:00Z",
  "interval": "1h",
  "items": {
    "USP-S | Printstream (Factory New)": {
      "market_hash_name": "USP-S | Printstream (Factory New)",
      "count": 72,
      "data": [
        {
          "bucket": "2026-07-20T00:00:00Z",
          "buff": {
            "open_ask": 115.16,
            "high_ask": 115.16,
            "low_ask": 115.16,
            "close_ask": 115.16,
            "ask_volume": 466,
            "open_bid": 112.21,
            "high_bid": 112.21,
            "low_bid": 112.21,
            "close_bid": 112.21,
            "bid_volume": 42,
            "sample_count": 75,
            "open_time": "2026-07-20T00:00:51Z",
            "close_time": "2026-07-20T00:58:51Z"
          },
          "youpin": {
            "open_ask": 113.54,
            "high_ask": 113.54,
            "low_ask": 113.54,
            "close_ask": 113.54,
            "ask_volume": 505,
            "open_bid": 112.5,
            "high_bid": 112.5,
            "low_bid": 112.5,
            "close_bid": 112.5,
            "bid_volume": 64,
            "sample_count": 12,
            "open_time": "2026-07-20T00:04:07Z",
            "close_time": "2026-07-20T00:58:07Z"
          },
          "csfloat": {
            "open_ask": 109.85,
            "high_ask": 109.85,
            "low_ask": 109.85,
            "close_ask": 109.85,
            "ask_volume": 229,
            "open_bid": 107,
            "high_bid": 107,
            "low_bid": 107,
            "close_bid": 107,
            "sample_count": 60,
            "open_time": "2026-07-20T00:00:25.313Z",
            "close_time": "2026-07-20T00:44:01.71Z"
          },
          "skinport": {
            "open_ask": 122.71,
            "high_ask": 122.71,
            "low_ask": 122.71,
            "close_ask": 122.71,
            "ask_volume": 43,
            "sample_count": 60,
            "open_time": "2026-07-20T00:00:29.985Z",
            "close_time": "2026-07-20T00:59:29.996Z"
          },
          "steam": {
            "open_ask": 161,
            "high_ask": 161.62,
            "low_ask": 161,
            "close_ask": 161.62,
            "ask_volume": 69,
            "open_bid": 155.43,
            "high_bid": 155.43,
            "low_bid": 155.43,
            "close_bid": 155.43,
            "bid_volume": 2940,
            "sample_count": 9,
            "open_time": "2026-07-20T00:02:52.014Z",
            "close_time": "2026-07-20T00:54:22.006Z"
          },
          "c5game": {
            "open_ask": 116.34,
            "high_ask": 116.34,
            "low_ask": 116.19,
            "close_ask": 116.19,
            "ask_volume": 147,
            "open_bid": 232.98,
            "high_bid": 232.98,
            "low_bid": 232.98,
            "close_bid": 232.98,
            "sample_count": 12,
            "open_time": "2026-07-20T00:02:49.997Z",
            "close_time": "2026-07-20T00:37:50.106Z"
          }
        }
      ]
    }
  }
}
```

## Response fields

[HistoryResponse](/docs/objects#historyresponse) fields:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `response_time` | `string (date-time)` | Yes | When the response was generated. |
| `currency` | `string` | Yes | Currency code (always `USD`). |
| `start` | `string (date-time)` | Yes | Effective start of the queried range, floored to the interval boundary. |
| `end` | `string (date-time)` | Yes | Effective end of the queried range, ceiled to the interval boundary. Exclusive. |
| `interval` | `string` | Yes | Allowed: `5m`, `30m`, `1h`, `1d`. OHLC bucket size. |
| `items` | [`Record<string, HistoryItem>`](/docs/objects#historyitem) | Yes | Map of `market_hash_name` to OHLC time-series. |
| `errors` | [ItemError[]](/docs/objects#itemerror) | No | Per-item failures alongside successful results (partial success). |

## Buckets

| Field | Description |
| --- | --- |
| `items.<name>.count` | Number of buckets with data. |
| `items.<name>.data[]` | OHLC buckets. |
| `data[].bucket` | UTC-aligned interval boundary. |
| `data[].<source>` | OHLC values, plus the real observation window (`open_time`/`close_time`) and `sample_count`. |
| `items.<name>.variants` | The same bucketed shape per variant. |

- `bucket` is present on every history bucket.
- Per-source objects appear only when that source has data in the bucket.
- `csfloat` carries ask and bid OHLC without `bid_volume`; `skinport` is ask-only.
- Valid requested items with no buckets in the requested range are omitted from `items`.

Full schemas: [HistoryItem](/docs/objects#historyitem), [HistoryBucket](/docs/objects#historybucket), and the per-source types under [OHLC Source Data](/docs/objects#ohlc-source-data).

### HistoryItem

OHLC time-series for a single item.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `market_hash_name` | `string` | Yes | Steam market hash name (the canonical item identifier). |
| `count` | `integer` | Yes | Number of buckets with data |
| `data` | [HistoryBucket[]](/docs/objects#historybucket) | Yes | OHLC buckets in chronological order. |
| `variants` | `Record<string, object>` | No | Per-variant OHLC time-series for items with Doppler / Gamma Doppler phases or Case Hardened tiers. Keyed by display name. |

### HistoryBucket

A single OHLC time bucket. `bucket` is the interval boundary (UTC-aligned, deterministic); `open_time`/`close_time` on each per-source object are the actual first/last observation timestamps inside it.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `bucket` | `string (date-time)` | Yes | Start of the time bucket. UTC-aligned to the interval boundary (e.g. `2026-01-08T19:00:00Z` for an `1h` bucket). Deterministic. |
| `buff` | [BUFFOHLCSourceData](/docs/objects#buffohlcsourcedata) | No | OHLC bucket of BUFF prices. |
| `youpin` | [YoupinOHLCSourceData](/docs/objects#youpinohlcsourcedata) | No | OHLC bucket of Youpin prices. |
| `csfloat` | [CsfloatOHLCSourceData](/docs/objects#csfloatohlcsourcedata) | No | OHLC bucket of CSFloat ask and bid prices. |
| `skinport` | [SkinportOHLCSourceData](/docs/objects#skinportohlcsourcedata) | No | OHLC bucket of Skinport ask prices. |
| `c5game` | [C5GameOHLCSourceData](/docs/objects#c5gameohlcsourcedata) | No | OHLC bucket of C5Game ask and bid prices. |
| `steam` | [SteamOHLCSourceData](/docs/objects#steamohlcsourcedata) | No | OHLC bucket of Steam Community Market ask and bid prices. |

## OHLC Source Data

### BUFFOHLCSourceData

OHLC bucket of BUFF prices.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `open_ask` | `number \| null` | Yes | First ask price in the bucket |
| `high_ask` | `number \| null` | Yes | Highest ask price in the bucket |
| `low_ask` | `number \| null` | Yes | Lowest ask price in the bucket |
| `close_ask` | `number \| null` | Yes | Last ask price in the bucket |
| `ask_volume` | `integer \| null` | Yes | Last observed ask volume in the bucket |
| `open_bid` | `number \| null` | Yes | First bid price in the bucket |
| `high_bid` | `number \| null` | Yes | Highest bid price in the bucket |
| `low_bid` | `number \| null` | Yes | Lowest bid price in the bucket |
| `close_bid` | `number \| null` | Yes | Last bid price in the bucket |
| `bid_volume` | `integer \| null` | Yes | Last observed bid volume in the bucket |
| `sample_count` | `integer` | Yes | Number of underlying 5-minute observations aggregated into this bucket |
| `open_time` | `string (date-time) \| null` | Yes | Timestamp of the first observation inside this bucket. Distinct from `bucket` (the interval boundary). |
| `close_time` | `string (date-time) \| null` | Yes | Timestamp of the last observation inside this bucket. Distinct from `bucket` (the interval boundary). |

### YoupinOHLCSourceData

OHLC bucket of Youpin prices.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `open_ask` | `number \| null` | Yes | First ask price in the bucket |
| `high_ask` | `number \| null` | Yes | Highest ask price in the bucket |
| `low_ask` | `number \| null` | Yes | Lowest ask price in the bucket |
| `close_ask` | `number \| null` | Yes | Last ask price in the bucket |
| `ask_volume` | `integer \| null` | Yes | Last observed ask volume in the bucket |
| `open_bid` | `number \| null` | Yes | First bid price in the bucket |
| `high_bid` | `number \| null` | Yes | Highest bid price in the bucket |
| `low_bid` | `number \| null` | Yes | Lowest bid price in the bucket |
| `close_bid` | `number \| null` | Yes | Last bid price in the bucket |
| `bid_volume` | `integer \| null` | Yes | Last observed bid volume in the bucket |
| `sample_count` | `integer` | Yes | Number of underlying 5-minute observations aggregated into this bucket |
| `open_time` | `string (date-time) \| null` | Yes | Timestamp of the first observation inside this bucket. Distinct from `bucket` (the interval boundary). |
| `close_time` | `string (date-time) \| null` | Yes | Timestamp of the last observation inside this bucket. Distinct from `bucket` (the interval boundary). |

### CsfloatOHLCSourceData

OHLC bucket of CSFloat ask and bid prices.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `open_ask` | `number \| null` | Yes | First ask price in the bucket |
| `high_ask` | `number \| null` | Yes | Highest ask price in the bucket |
| `low_ask` | `number \| null` | Yes | Lowest ask price in the bucket |
| `close_ask` | `number \| null` | Yes | Last ask price in the bucket |
| `ask_volume` | `integer \| null` | Yes | Last observed ask volume in the bucket |
| `open_bid` | `number \| null` | Yes | First bid price in the bucket |
| `high_bid` | `number \| null` | Yes | Highest bid price in the bucket |
| `low_bid` | `number \| null` | Yes | Lowest bid price in the bucket |
| `close_bid` | `number \| null` | Yes | Last bid price in the bucket |
| `sample_count` | `integer` | Yes | Number of underlying 5-minute observations aggregated into this bucket |
| `open_time` | `string (date-time) \| null` | Yes | Timestamp of the first observation inside this bucket. Distinct from `bucket` (the interval boundary). |
| `close_time` | `string (date-time) \| null` | Yes | Timestamp of the last observation inside this bucket. Distinct from `bucket` (the interval boundary). |

### SkinportOHLCSourceData

OHLC bucket of Skinport ask prices.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `open_ask` | `number \| null` | Yes | First ask price in the bucket |
| `high_ask` | `number \| null` | Yes | Highest ask price in the bucket |
| `low_ask` | `number \| null` | Yes | Lowest ask price in the bucket |
| `close_ask` | `number \| null` | Yes | Last ask price in the bucket |
| `ask_volume` | `integer \| null` | Yes | Last observed ask volume in the bucket |
| `sample_count` | `integer` | Yes | Number of underlying 5-minute observations aggregated into this bucket |
| `open_time` | `string (date-time) \| null` | Yes | Timestamp of the first observation inside this bucket. Distinct from `bucket` (the interval boundary). |
| `close_time` | `string (date-time) \| null` | Yes | Timestamp of the last observation inside this bucket. Distinct from `bucket` (the interval boundary). |

### SteamOHLCSourceData

OHLC bucket of Steam Community Market ask and bid prices.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `open_ask` | `number \| null` | Yes | First ask price in the bucket |
| `high_ask` | `number \| null` | Yes | Highest ask price in the bucket |
| `low_ask` | `number \| null` | Yes | Lowest ask price in the bucket |
| `close_ask` | `number \| null` | Yes | Last ask price in the bucket |
| `ask_volume` | `integer \| null` | Yes | Last observed ask volume in the bucket |
| `open_bid` | `number \| null` | Yes | First bid price in the bucket |
| `high_bid` | `number \| null` | Yes | Highest bid price in the bucket |
| `low_bid` | `number \| null` | Yes | Lowest bid price in the bucket |
| `close_bid` | `number \| null` | Yes | Last bid price in the bucket |
| `bid_volume` | `integer \| null` | Yes | Last observed bid volume in the bucket |
| `sample_count` | `integer` | Yes | Number of underlying 5-minute observations aggregated into this bucket |
| `open_time` | `string (date-time) \| null` | Yes | Timestamp of the first observation inside this bucket. Distinct from `bucket` (the interval boundary). |
| `close_time` | `string (date-time) \| null` | Yes | Timestamp of the last observation inside this bucket. Distinct from `bucket` (the interval boundary). |

### C5GameOHLCSourceData

OHLC bucket of C5Game ask and bid prices.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `open_ask` | `number \| null` | Yes | First ask price in the bucket |
| `high_ask` | `number \| null` | Yes | Highest ask price in the bucket |
| `low_ask` | `number \| null` | Yes | Lowest ask price in the bucket |
| `close_ask` | `number \| null` | Yes | Last ask price in the bucket |
| `ask_volume` | `integer \| null` | Yes | Last observed ask volume in the bucket |
| `open_bid` | `number \| null` | Yes | First bid price in the bucket |
| `high_bid` | `number \| null` | Yes | Highest bid price in the bucket |
| `low_bid` | `number \| null` | Yes | Lowest bid price in the bucket |
| `close_bid` | `number \| null` | Yes | Last bid price in the bucket |
| `sample_count` | `integer` | Yes | Number of underlying 5-minute observations aggregated into this bucket |
| `open_time` | `string (date-time) \| null` | Yes | Timestamp of the first observation inside this bucket. Distinct from `bucket` (the interval boundary). |
| `close_time` | `string (date-time) \| null` | Yes | Timestamp of the last observation inside this bucket. Distinct from `bucket` (the interval boundary). |

## Errors

When only some item names fail, the endpoint returns `200` with the successful series and `errors[]`. Valid items with no buckets in the requested range are omitted without an item error. See [Partial success](/docs/using-the-api#partial-success) and [Request errors](/docs/using-the-api#request-errors).
