# POST /v1/archive/history

Long-term archive prices, total supply, and sale volume from 2023 onward.

Returns long-term listing-price history from BUFF, Youpin, C5Game, and an `aggregate` series. Data begins in 2023 and updates ~1-2x per day. Max 100 items per request.

Within each bucket, prices, listing volumes, and `total_supply` are the last observed values. `hourly_volume` is an approximate sale count: the hourly estimate in `1h` responses, and the sum of those hourly estimates in each `1d` bucket.

## Access

Requires a Scale or Enterprise API key.

## Supported intervals

| Interval | Bucket |
| --- | --- |
| `1h` | Hourly archive buckets |
| `1d` | Daily archive buckets |

## Supported sources

| Source | Fields |
| --- | --- |
| `aggregate` | `ask`, `bid`, `ask_volume`, `bid_volume`, `hourly_volume`, `total_supply` |
| `buff` | `ask`, `bid`, `ask_volume`, `bid_volume` |
| `youpin` | `ask`, `bid`, `ask_volume`, `bid_volume` |
| `c5game` | `ask`, `bid`, `ask_volume`, `bid_volume` |

By default, only `aggregate` is returned.

## Request

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

**curl**

```bash
curl -X POST https://api.cs2.sh/v1/archive/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": "2024-01-01",
  "end": "2026-07-26",
  "sources": [
    "aggregate",
    "buff"
  ],
  "interval": "1d"
}'
```

**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": "2024-01-01",
    "end": "2026-07-26",
    "sources": ["aggregate", "buff"],
    "interval": "1d",
}

response = requests.post(
    "https://api.cs2.sh/v1/archive/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/archive/history", {
  method: "POST",
  headers,
  body: JSON.stringify({
    "items": [
      "USP-S | Printstream (Factory New)"
    ],
    "start": "2024-01-01",
    "end": "2026-07-26",
    "sources": [
      "aggregate",
      "buff"
    ],
    "interval": "1d"
  }),
});

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": "2024-01-01",
        "end": "2026-07-26",
        "sources": []any{
            "aggregate",
            "buff",
        },
        "interval": "1d",
    }
    body, _ := json.Marshal(payload)
    req, _ := http.NewRequest("POST", "https://api.cs2.sh/v1/archive/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 = "2024-01-01",
  end = "2026-07-26",
  sources = list(
    "aggregate",
    "buff"
  ),
  interval = "1d"
)

resp <- request("https://api.cs2.sh/v1/archive/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: aggregate only. |
| `interval` | `string` | No | Default: `1d`. Allowed: `1h`, `1d`. Aggregation interval |

## Response

```json
{
  "response_time": "2026-07-26T18:54:19.138233339Z",
  "currency": "USD",
  "start": "2026-04-27T00:00:00Z",
  "end": "2026-07-25T00:00:00Z",
  "interval": "1d",
  "items": {
    "USP-S | Printstream (Factory New)": {
      "market_hash_name": "USP-S | Printstream (Factory New)",
      "count": 89,
      "data": [
        {
          "bucket": "2026-04-27T00:00:00Z",
          "aggregate": {
            "time": "2026-04-27T23:59:07Z",
            "ask": 130.05,
            "ask_volume": 1225,
            "bid": 130.19,
            "bid_volume": 133,
            "hourly_volume": 27,
            "total_supply": 31291,
            "sample_count": 24
          },
          "buff": {
            "time": "2026-04-27T23:53:24Z",
            "ask": 133.12,
            "ask_volume": 405,
            "bid": 130.19,
            "bid_volume": 45,
            "sample_count": 24
          },
          "youpin": {
            "time": "2026-04-27T23:59:07Z",
            "ask": 130.05,
            "ask_volume": 510,
            "bid": 128.59,
            "bid_volume": 63,
            "sample_count": 24
          },
          "c5game": {
            "time": "2026-04-27T23:57:07Z",
            "ask": 132.21,
            "ask_volume": 139,
            "bid": 213.58,
            "bid_volume": 24,
            "sample_count": 24
          }
        }
      ]
    }
  }
}
```

## Response fields

[ArchiveHistoryResponse](/docs/objects#archivehistoryresponse) 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: `1h`, `1d`. Archive bucket size. |
| `items` | [`Record<string, ArchiveHistoryItem>`](/docs/objects#archivehistoryitem) | Yes | Map of `market_hash_name` to archive 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[]` | Archive buckets. |
| `data[].bucket` | Bucket boundary. |
| `data[].<platform>` | Last-observed `ask`/`bid` and `ask_volume`/`bid_volume`, with `time` and `sample_count`. Platforms: `aggregate`, `buff`, `youpin`, `c5game`. |
| `data[].aggregate.hourly_volume` | Approximate sales for the bucket. Hourly for `1h`; summed across the day for `1d`. |
| `data[].aggregate.total_supply` | Approximate cumulative supply of the item. `aggregate` only. |

- `bucket` is present on every archive bucket.
- Per-platform objects appear only when that platform has data in the bucket.
- Valid requested items with no archive data return `not_in_archive`.

Full schemas: [ArchiveHistoryItem](/docs/objects#archivehistoryitem), [ArchiveHistoryBucket](/docs/objects#archivehistorybucket), [ArchiveHistoryPlatformData](/docs/objects#archivehistoryplatformdata).

### ArchiveHistoryItem

Long-term archive time-series for a single item.

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

### ArchiveHistoryBucket

A single archive time bucket. Each platform key is present only when data exists for that platform in this bucket.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `bucket` | `string (date-time)` | Yes | Start of the time bucket (UTC-aligned to the interval boundary). |
| `aggregate` | [ArchiveHistoryPlatformData](/docs/objects#archivehistoryplatformdata) | No | Per-platform price data within an archive bucket. `hourly_volume` and `total_supply` are populated only on the `aggregate` platform. |
| `buff` | [ArchiveHistoryPlatformData](/docs/objects#archivehistoryplatformdata) | No | Per-platform price data within an archive bucket. `hourly_volume` and `total_supply` are populated only on the `aggregate` platform. |
| `youpin` | [ArchiveHistoryPlatformData](/docs/objects#archivehistoryplatformdata) | No | Per-platform price data within an archive bucket. `hourly_volume` and `total_supply` are populated only on the `aggregate` platform. |
| `c5game` | [ArchiveHistoryPlatformData](/docs/objects#archivehistoryplatformdata) | No | Per-platform price data within an archive bucket. `hourly_volume` and `total_supply` are populated only on the `aggregate` platform. |

### ArchiveHistoryPlatformData

Per-platform price data within an archive bucket. `hourly_volume` and `total_supply` are populated only on the `aggregate` platform.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `time` | `string (date-time)` | Yes | Actual timestamp of the last observation in the bucket. Distinct from the bucket boundary. |
| `ask` | `number \| null` | Yes | Last observed ask price (USD) in the bucket. |
| `ask_volume` | `integer \| null` | Yes | Last observed number of items listed for sale. |
| `bid` | `number \| null` | Yes | Last observed bid price (USD) in the bucket. |
| `bid_volume` | `integer \| null` | Yes | Last observed number of buy orders. |
| `hourly_volume` | `number \| null` | No | Aggregated trading volume metric (`aggregate` platform only). |
| `total_supply` | `number \| null` | No | Total market supply metric (`aggregate` platform only). |
| `sample_count` | `integer` | Yes | Number of observations aggregated into this bucket. |

## Errors

`404 not_found` means none of the requested valid items have archive data. Partial results return `200` with `errors[]`; possible item codes are `unknown_item`, `invalid_format`, and `not_in_archive`. See [Partial success](/docs/using-the-api#partial-success) and [Request errors](/docs/using-the-api#request-errors).
