> ## Documentation Index
> Fetch the complete documentation index at: https://api.csboard.com/llms.txt
> Use this file to discover all available pages before exploring further.

# GET /v1/listings/snapshot.ndjson.gz — Every Listing in One File

> Download every buyable CSBoard listing as one gzipped NDJSON file, then keep it current from the SSE stream. The replacement for paging the whole catalogue.

Every buyable listing as one gzipped NDJSON file. Each decompressed line is one `Listing` JSON object — the exact shape [`GET /v1/listings`](/api-reference/get-listings) returns, with the same one-listing-per-physical-skin rule and your negotiated discount already applied.

This is the way to hold a complete local copy of the shelf. Walking [`/v1/listings`](/api-reference/get-listings) page by page works for a filtered subset; for everything, it is tens of thousands of reads per pass. Download this file once instead, then open [`/v1/listings/stream`](/api-reference/get-listings-stream) from the position the file hands you, and your copy stays current from there.

**Authentication required.** Send your key as `Authorization: Bearer csb_pub_...`.

**Limit:** six full downloads per hour per key. A `304` answer to a conditional request is free.

## The pairing: file + stream

1. Download the file. Keep the `ETag` and the `X-Stream-Position` response headers.
2. Connect to `/v1/listings/stream?last_event_id=<X-Stream-Position>`. The stream replays everything that happened since the file was built, then goes live. Apply `new` as an **upsert by `id`** (a listing may already be in your copy) and `gone` as a delete.
3. Re-download on your own cadence — hourly is plenty — with `If-None-Match`. A reprice of a listing that was already live is not a stream event; the next file carries it. Between files a stale price is refused at checkout with `price_moved`, never filled.

If the stream answers `resync`, your position has aged out of its history: download the file again and reconnect from its new `X-Stream-Position`.

## Request headers

**If-None-Match** `string`

The `ETag` from your previous download. Unchanged → `304 Not Modified`, no body, no charge against the hourly limit.

**If-Modified-Since** `string`

The `Last-Modified` from your previous download. Same effect as `If-None-Match`.

## Response headers

| Header | Description |
| - | - |
| `ETag` | Opaque version of this file. Send it back as `If-None-Match`. |
| `Last-Modified` | When this file was built (HTTP date). |
| `X-Snapshot-At` | The same build time, ISO-8601 with milliseconds. |
| `X-Stream-Position` | The stream event id to connect with (`last_event_id`) so nothing between this file and your live view is missed. |
| `X-Row-Count` | Number of listings in the file. |
| `Content-Encoding` | `gzip` — the body is always compressed; `Content-Length` is the compressed size. |

## Response body

A gzip stream. Every decompressed line is a `Listing`:

```jsonl theme={null}
{"id":"000012e8-1f4a-4c2b-9d3e-7a1b2c3d4e5f","market_hash_name":"AK-47 | Redline (Field-Tested)","wear":"Field-Tested","doppler_phase":null,"float_value":0.2613,"paint_seed":661,"stickers":[{"name":"Sticker | Natus Vincere | Katowice 2015","image":"https://…","slot":2,"wear":0.12}],"price_usd":31.2,"category":"Rifle","rarity":"Classified","image":"https://…","inspect_link":"steam://rungame/730/…","tradable":true,"tradable_at":null,"delivery":"instant","refund_percent":100,"listed_at":"2026-10-20T09:14:02.481Z"}
```

The file is not filtered: all three `delivery` buckets (`instant`, `up_to_12h`, `hold`) are in it. Filter on the field locally. It is rebuilt every 10 minutes while anyone is downloading it, CS2 only (`appId` is not read).

## Example: download, then stream from the file's position

```bash theme={null}
curl https://csboard.com/v1/listings/snapshot.ndjson.gz \
  -H "Authorization: Bearer csb_pub_..." \
  --dump-header headers.txt \
  --output listings.ndjson.gz

POS=$(grep -i '^x-stream-position' headers.txt | awk '{print $2}' | tr -d '\r')

curl -N "https://csboard.com/v1/listings/stream?last_event_id=$POS" \
  -H "Authorization: Bearer csb_pub_..." \
  -H "Accept: text/event-stream"
```

## Example: conditional re-download

```bash theme={null}
curl https://csboard.com/v1/listings/snapshot.ndjson.gz \
  -H "Authorization: Bearer csb_pub_..." \
  -H 'If-None-Match: "lsnap-1792000000000-3900000"' \
  --output listings.ndjson.gz
```

`304` means your file is the current one.

## Responses other than 200

| HTTP status | Code | Meaning |
| - | - | - |
| 202 | `snapshot_building` | No file exists yet — the first minutes after a deploy. Retry after `Retry-After` seconds (also in `retry_after_seconds`). |
| 304 | *(no body)* | Unchanged since the `ETag` or date you sent. |
| 401 | `missing_api_key`, `invalid_api_key` | Missing or invalid API key. |
| 429 | `snapshot_rate_limited` | More than six full downloads this hour. Send `If-None-Match` and take live changes from the stream. |

> [!NOTE]
>
> The price list by name — one row per `market_hash_name` with its cheapest ask — is a different, much smaller file: [`GET /v1/prices/snapshot.ndjson.gz`](/api-reference/get-prices-snapshot).


## OpenAPI

````yaml GET /listings/snapshot.ndjson.gz
openapi: 3.1.0
info:
  title: CSBoard API
  version: 1.0.0
  description: >-
    Market data over the CSBoard marketplace — live listings, floats, stickers,
    minAsk prices, FX rates — plus opt-in buying straight from your balance.
    Free to read, key-gated, built for automation.
  contact:
    name: CSBoard
    url: https://csboard.com/docs
servers:
  - url: https://csboard.com/v1
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Status
    description: Liveness and freshness probes.
  - name: Market data
    description: Read the live catalog, prices, and FX rates.
  - name: Trading
    description: Buy listings from your CSBoard balance. Opt-in, key-gated.
  - name: Instant Sell
    description: >-
      Sell CS2, Dota 2 and Rust items from any Steam inventory to the CSBoard
      network and get paid to your balance. Invite-only.
  - name: P2P
    description: >-
      List your own CS2 skins on the CSBoard P2P market. Free — any valid key,
      no balance requirement.
  - name: Account
    description: Your balance, settled funds, and trading status.
  - name: Webhooks
    description: Register an endpoint and receive signed order updates instead of polling.
paths:
  /listings/snapshot.ndjson.gz:
    get:
      tags:
        - Market data
      summary: Every buyable listing in one file (gzipped NDJSON)
      description: >-
        The whole shelf as gzipped NDJSON — one Listing JSON object per line, in
        the exact shape GET /listings returns, one listing per physical skin.
        Rebuilt every 10 minutes while anyone downloads it. Pair it with GET
        /listings/stream: connect with `last_event_id` set to this response's
        `X-Stream-Position` header and apply `new` as an upsert by id, `gone` as
        a delete. Reprices of listings that were already live are not stream
        events, so re-download on your own cadence; a stale price is refused at
        checkout with `price_moved`. Supports ETag / If-None-Match and
        Last-Modified / If-Modified-Since (304). Six full downloads per hour per
        key; a 304 is free. CS2 only — this endpoint does not read `appId`.
      operationId: getListingsSnapshot
      parameters:
        - name: If-None-Match
          in: header
          description: >-
            Conditional request. Pass the ETag from a previous download to
            receive 304 if unchanged.
          schema:
            type: string
        - name: If-Modified-Since
          in: header
          description: Conditional request by the previous Last-Modified value.
          schema:
            type: string
      responses:
        '200':
          description: Gzipped NDJSON. Each decompressed line is one Listing JSON object.
          headers:
            ETag:
              description: >-
                Opaque snapshot version. Send back as If-None-Match to skip
                unchanged downloads.
              schema:
                type: string
            Last-Modified:
              description: When this snapshot was built.
              schema:
                type: string
            X-Stream-Position:
              description: >-
                The /listings/stream event id to connect with (`last_event_id`)
                so nothing between this file and your live view is missed.
              schema:
                type: string
            X-Row-Count:
              description: Number of listings in the file.
              schema:
                type: integer
            X-Snapshot-At:
              description: Build time, ISO-8601 with milliseconds.
              schema:
                type: string
          content:
            application/x-ndjson:
              schema:
                type: string
                format: binary
        '202':
          description: >-
            No snapshot exists yet (the first minutes after a deploy). Body `{
            code: "snapshot_building", retry_after_seconds }`; retry after
            `Retry-After` seconds.
        '304':
          description: >-
            Not Modified — the snapshot has not changed since the ETag or date
            you sent.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          description: >-
            `snapshot_rate_limited` — more than six full downloads this hour.
            Send If-None-Match and take live changes from the stream.
components:
  responses:
    Unauthorized:
      description: Missing or invalid API key (`missing_api_key` or `invalid_api_key`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: missing_api_key
            detail: >-
              Provide your API key via `Authorization: Bearer csb_pub_…`.
              Generate one at https://csboard.com/profile?tab=api
  schemas:
    Error:
      type: object
      description: >-
        All errors return { code, detail }. Some carry extra fields (e.g.
        price_moved adds current_total_usd, insufficient_balance adds
        required_usd/current_usd).
      properties:
        code:
          type: string
          description: >-
            Machine-readable error code, e.g. rate_limit_exceeded,
            trading_not_enabled, price_moved.
        detail:
          type: string
          description: Human-readable explanation.
      required:
        - code
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Send your key as a Bearer token on every request: `Authorization: Bearer
        csb_pub_...`. Generate keys in your CSBoard profile.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.