openapi: 3.1.0
info:
  title: CS Price API
  version: 1.4.0
  description: |-
    ## Freshness

    Most prices update about every 5 minutes, depending on the marketplace. Doppler phases included.

    Public price API for the CS2 (Counter-Strike 2) skin ecosystem.

    Latest listing prices are available via a single item-centric endpoint
    `GET` / `POST` `/v1/prices/latest` (optional `markets` filter). Use
    `/v1/prices/search` for one skin with Doppler phase expansion, plus
    buy-orders, float-ranged, price history and market-sales export.

    Subscription customers can additionally download a daily **ZIP export** of
    historical marketplace sales (`/v1/market-sales/export`) as three CSV files
    (sales, stickers, keychains) covering the last 24 hours.

    ## Subscription plans

    API access is grouped by plan. Higher tiers include all endpoints from lower
    tiers:

    | Plan | Included categories |
    |------|---------------------|
    | **Basic** | Listing Prices |
    | **Pro** | Basic + Buyorder Prices + Float Ranged |
    | **Enterprise** | Pro + Price History + Sales Data (full API access) |

    Each API key is issued for a specific plan and may be further restricted via
    endpoint ACL (`allowed_endpoints`).

    ## Authentication

    Every non-documentation endpoint requires an API key in the `x-api-key`
    request header. Keys are issued per customer and optionally scoped to a
    subset of endpoints (endpoint ACL). They also enforce a per-minute and
    per-day rate limit.


    ## Response format stability

    All response shapes documented here reflect what the server **currently**
    returns. In particular:

    - Numeric fields for prices, percentage changes, averages and liquidity
      are serialized as **strings**, not numbers.
      Example: `"price_rmb": "7333.0000"`. Clients must parse them as
      fixed-point / arbitrary-precision decimals.
    - `stattrak` and `souvenir` are serialized as **integers** (`0` or `1`),
      not booleans.
    - `updated_at` is ISO-8601 UTC (`YYYY-MM-DDTHH:mm:ss.sssZ`).
    - `liquidity` is an internal liquidity score and may be `null` if
      unavailable for that skin.
  contact:
    name: CS Price API Support
    url: https://cspriceapi.com
servers:
  - url: https://api.cspriceapi.com
    description: Production
  - url: http://localhost:8080
    description: Local development
tags:
  - name: Listing Prices
    description: |-
      Most prices update about every 5 minutes, depending on the marketplace. Doppler phases included.

      Latest listing prices across marketplaces via `/v1/prices/latest`, plus
      the single-skin `/v1/prices/search` helper.

      **Plan: Basic** (included in Pro and Enterprise).
  - name: Buyorder Prices
    description: |-
      Most prices update about every 5 minutes, depending on the marketplace. Doppler phases included.

      Buy-order price data from supported marketplaces.

      **Plan: Pro** (included in Enterprise).
  - name: Float Ranged
    description: |-
      Most prices update about every 5 minutes, depending on the marketplace. Doppler phases included.

      Float-range filtered listing prices (buckets such as `0.00-0.07`),
      including listing counts, phase translations for Doppler skins, and fade
      percentage for Fade skins.

      **Plan: Pro** (included in Enterprise).
  - name: Price History
    description: |
      Historical listing prices per marketplace. Use `resolution=hourly` for up
      to ~100 days (≈24 points/day) or `resolution=daily` for the full daily
      series (1 point/day). Exactly one `market_hash_name` per request.

      **Plan: Enterprise**.
  - name: Sales Data
    description: |
      Daily ZIP/CSV bulk export of historical marketplace sales.
      Requires a subscription API key scoped to `/v1/market-sales/export`.

      **Plan: Enterprise** (includes all API endpoints).
security:
  - ApiKeyAuth: []
paths:
  /v1/prices/latest:
    get:
      tags:
        - Listing Prices
      summary: Latest listing prices across marketplaces (Basic)
      description: |
        Returns the latest prices for all items across supported marketplaces
        (YouPin, Buff163, C5Game, EcoSteam, SkinBaron, Skinport, CSFloat,
        Lisskins, DMarket, ShadowPay, Waxpeer, Steam, Market.CSGO).

        Most prices update about every 5 minutes, depending on the marketplace.
        Optional `markets` filters which sources are included. Prefer gzip —
        full snapshots are large. Prices use each marketplace's native currency.
      operationId: getLatestPrices
      parameters:
        - name: markets
          in: query
          required: false
          description: |
            Comma-separated marketplace slugs (e.g. `youpin,buff163,steam`).
            Omit to include all listing marketplaces your key is allowed to access.
          schema:
            type: string
            example: youpin,buff163,steam
      responses:
        "200":
          description: Latest prices keyed by market_hash_name.
          headers:
            Cache-Control:
              schema:
                type: string
                example: public, max-age=30
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/LatestPricesResponse"
              examples:
                ok:
                  summary: Two marketplaces, one skin excerpt
                  value:
                    items:
                      AK-47 | Redline (Field-Tested):
                        market_hash_name: AK-47 | Redline (Field-Tested)
                        youpin:
                          id: 210
                          market_hash_name: AK-47 | Redline (Field-Tested)
                          stattrak: 0
                          souvenir: 0
                          price_rmb: "142.00"
                          change_24h: "0.30"
                          change_7d: "1.10"
                          change_30d: "-0.80"
                          change_90d: "4.20"
                          avg_7d: "141.20"
                          avg_30d: "143.80"
                          avg_90d: "136.00"
                          count: 612
                          phase: ""
                          updated_at: 2026-04-21T12:06:35.000Z
                          youpin_template_id: 1021
                          liquidity: "8.90"
                        buff163:
                          id: 62235
                          market_hash_name: AK-47 | Redline (Field-Tested)
                          stattrak: 0
                          souvenir: 0
                          exterior: Field-Tested
                          price: "138.80"
                          change_24h: "0.10"
                          change_7d: "0.90"
                          change_30d: "-1.10"
                          change_90d: "3.80"
                          avg_7d: "138.20"
                          avg_30d: "140.10"
                          avg_90d: "133.50"
                          count: 1203
                          updated_at: 2026-04-21T12:20:00.000Z
                          item_page_url: https://buff.163.com/goods/35247
                          liquidity: "9.10"
                    markets:
                      - youpin
                      - buff163
                    requestor: customer@example.com
                    plan: pro
                    timestamp: 2026-08-27T14:50:00.000Z
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
    post:
      tags:
        - Listing Prices
      summary: Latest prices for selected items (Basic)
      description: |
        Same latest-price data as `GET /v1/prices/latest`, filtered to up to
        **100** requested `market_hash_name` values.

        Most prices update about every 5 minutes, depending on the marketplace.
        Optional `markets` limits which sources are loaded. Missing items appear
        in `errors` (`not_found`); if none match, the API returns `404`.
      operationId: postLatestPrices
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - items
              properties:
                items:
                  type: array
                  minItems: 1
                  maxItems: 100
                  items:
                    type: string
                  description: market_hash_name values to look up.
                  example:
                    - AK-47 | Redline (Field-Tested)
                    - USP-S | Printstream (Factory New)
                markets:
                  type: array
                  items:
                    type: string
                  description: Optional marketplace filter (same slugs as GET).
                  example:
                    - youpin
                    - buff163
                    - csfloat
            examples:
              filter:
                value:
                  items:
                    - AK-47 | Redline (Field-Tested)
                  markets:
                    - youpin
                    - buff163
      parameters:
        - name: markets
          in: query
          required: false
          description: Optional CSV marketplace filter if not sent in the JSON body.
          schema:
            type: string
      responses:
        "200":
          description: Latest prices for the requested items (partial success possible).
          headers:
            Cache-Control:
              schema:
                type: string
                example: public, max-age=30
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/LatestPricesResponse"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: None of the requested items were found.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  errors:
                    type: array
                    items:
                      $ref: "#/components/schemas/LatestItemError"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
  /v1/prices/youpin/buyorder:
    get:
      tags:
        - Buyorder Prices
      summary: Get current YouPin buy-order prices (Pro)
      description: |-
        Returns YouPin buy-order bids (and the separate "blue" buy-order price
        used for certain items, e.g. Dopplers) for every tracked skin.

        Most prices update about every 5 minutes, depending on the marketplace. Doppler phases included.
      operationId: getYoupinBuyorders
      responses:
        "200":
          description: Successful response with current YouPin buy-orders.
          headers:
            Cache-Control:
              schema:
                type: string
                example: public, max-age=30
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/YoupinBuyorderResponse"
              examples:
                ok:
                  value:
                    data:
                      - id: 2
                        market_hash_name: AK-47 | Redline (Field-Tested)
                        templateId: 57912
                        buyorder_price: "120.00"
                        blue_buyorder_price: "118.00"
                        phase: ""
                        typeId: 42
                        updated_at: 2026-04-21T12:15:00.000Z
                        count: 280
                      - id: 1
                        market_hash_name: Glock-18 | Gamma Doppler (Factory New) (Phase 2)
                        templateId: 57912
                        buyorder_price: "1122.50"
                        blue_buyorder_price: "980.00"
                        phase: Phase 2
                        typeId: 42
                        updated_at: 2026-04-21T12:15:00.000Z
                        count: 36
                    source: YouPin
                    requestor: customer@example.com
                    plan: pro
                    timestamp: 2026-04-21T12:20:00.000Z
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
  /v1/prices/{market}/history:
    get:
      tags:
        - Price History
      summary: Get historical prices for one skin (Enterprise)
      description: |
        Returns historical listing prices for **exactly one**
        `market_hash_name` on a given marketplace.


        | `resolution` | Source | Density | Typical retention |
        |--------------|--------|---------|-------------------|
        | `hourly` | `price_history_*` | up to 24 points/day (`slot`) | last ~100 days |
        | `daily` (default) | `price_daily_*` | 1 point/day | full history |

        Requesting `hourly` for a `from`/`to` window longer than **100 days**
        returns `400` — use `daily` for longer ranges.


        `youpin`, `buff163`, `c5game`, `skinport`, `skinbaron`, `market-csgo`,
        `csfloat`, `dmarket`, `ecosteam`, `lisskins`, `skinland`, `shadowpay`,
        `waxpeer`.


        Prices are decimal **strings** in the marketplace's native currency
        (`currency` in the response): CNY / EUR / USD. CSFloat history is stored
        in USD cents and converted to USD for the response.
      operationId: getMarketPriceHistory
      parameters:
        - name: market
          in: path
          required: true
          schema:
            type: string
            enum:
              - youpin
              - buff163
              - c5game
              - skinport
              - skinbaron
              - market-csgo
              - csfloat
              - dmarket
              - ecosteam
              - lisskins
              - skinland
              - shadowpay
              - waxpeer
          description: Marketplace slug (same as live price routes).
        - name: market_hash_name
          in: query
          required: true
          description: |
            Steam `market_hash_name`. **Only one** name per request
            (no comma-separated lists, no repeated params).
          schema:
            type: string
            minLength: 1
          example: AK-47 | Redline (Field-Tested)
        - name: resolution
          in: query
          required: false
          schema:
            type: string
            enum:
              - hourly
              - daily
            default: daily
          description: Point density. Defaults to `daily`.
        - name: from
          in: query
          required: false
          schema:
            type: string
            format: date
          description: |
            Inclusive start date (`YYYY-MM-DD`). Defaults to 30 days before `to`
            for `hourly`, or 365 days before `to` for `daily`.
        - name: to
          in: query
          required: false
          schema:
            type: string
            format: date
          description: Inclusive end date (`YYYY-MM-DD`). Defaults to today (UTC).
      responses:
        "200":
          description: Historical price series for the requested skin.
          headers:
            Cache-Control:
              schema:
                type: string
                example: public, max-age=60
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PriceHistoryResponse"
              examples:
                daily:
                  summary: Daily resolution
                  value:
                    market: youpin
                    market_hash_name: AK-47 | Redline (Field-Tested)
                    resolution: daily
                    currency: CNY
                    from: 2025-08-21
                    to: 2026-08-21
                    count: 2
                    data:
                      - day: 2025-08-21
                        price: "210.5000"
                        count: 8421
                      - day: 2026-08-21
                        price: "185.5000"
                        count: 11507
                    source: YouPin History
                    requestor: customer@example.com
                    plan: enterprise
                    timestamp: 2026-08-21T06:00:00.000Z
                hourly:
                  summary: Hourly resolution
                  value:
                    market: youpin
                    market_hash_name: AK-47 | Redline (Field-Tested)
                    resolution: hourly
                    currency: CNY
                    from: 2026-07-22
                    to: 2026-08-21
                    count: 2
                    data:
                      - day: 2026-08-20
                        slot: 10
                        last_ts: 2026-08-20 10:15:00
                        price: "186.2000"
                        count: 11404
                      - day: 2026-08-20
                        slot: 11
                        last_ts: 2026-08-20 11:15:00
                        price: "186.2600"
                        count: 11420
                    source: YouPin History
                    requestor: customer@example.com
                    plan: enterprise
                    timestamp: 2026-08-21T06:00:00.000Z
        "400":
          description: Invalid parameters or hourly range too long.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                multi:
                  value:
                    error: Only one market_hash_name is allowed per request
                hourlyTooLong:
                  value:
                    error: hourly resolution supports at most 100 days; use resolution=daily for longer ranges
                    from: 2025-01-01
                    to: 2026-08-21
                    days: 598
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: Unknown marketplace slug.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
  /v2/prices/float-ranged:
    get:
      tags:
        - Float Ranged
      summary: Get float-ranged prices v2 (Pro)
      description: |-
        Returns float-ranged listing prices (v2).

        This v2 payload is intentionally slim and only includes:
        `market_hash_name`, `float_range`, `phase`, `fade`, `count`,
        `price_rmb` and `updated_at`.

        The `phase` field is translated to English where applicable.
        `fade` is the fade percentage for Fade skins (otherwise `null`).

        Most prices update about every 5 minutes, depending on the marketplace. Doppler phases included.
      operationId: getFloatRangedPricesV2
      responses:
        "200":
          description: Successful response with float-ranged v2 data.
          headers:
            Cache-Control:
              schema:
                type: string
                example: public, max-age=30
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FloatRangedV2PricesResponse"
              examples:
                ok:
                  value:
                    data:
                      - market_hash_name: Glock-18 | Gamma Doppler (Factory New)
                        float_range: 0.00-0.07
                        phase: Phase 2
                        fade: null
                        count: 12
                        price_rmb: "1230.0000"
                        updated_at: 2026-04-21T12:00:00.000Z
                      - market_hash_name: AWP | Fade (Factory New)
                        float_range: 0.00-0.01
                        phase: null
                        fade: 81.7
                        count: 3
                        price_rmb: "5088.8200"
                        updated_at: 2026-08-06T12:00:00.000Z
                    source: Float Ranged
                    requestor: customer@example.com
                    plan: pro
                    timestamp: 2026-04-21T12:20:35.000Z
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
  /v1/prices/search:
    get:
      tags:
        - Listing Prices
      summary: Look up a specific skin across all marketplaces (Basic)
      description: |-
        Fetches the current price of a single `market_hash_name` from every
        supported marketplace in one request.


        If the query looks like a Doppler or Gamma Doppler skin (case-insensitive
        substring `doppler`), the server strips any existing phase annotation
        from the input and queries **all** phase variants in parallel:

        - Regular Doppler: `(Ruby)`, `(Sapphire)`, `(Black Pearl)`,
          `(Phase 1)`..`(Phase 4)`
        - Gamma Doppler: `(Emerald)`, `(Phase 1)`..`(Phase 4)`

        The phase suffix is appended **after** the exterior, e.g.
        `Glock-18 | Gamma Doppler (Factory New) (Phase 2)`.

        The response schema therefore differs between the two cases:

        - `is_doppler: false` → per marketplace either a single item object or `null`.
        - `is_doppler: true`  → per marketplace an **array** of matched phase variants (possibly empty).

        Clients should branch on the top-level `is_doppler` flag to select the
        correct variant.

        Most prices update about every 5 minutes, depending on the marketplace. Doppler phases included.
      operationId: searchSkin
      parameters:
        - $ref: "#/components/parameters/MarketHashNameQuery"
      responses:
        "200":
          description: Successful response. Payload shape depends on `is_doppler`.
          headers:
            Cache-Control:
              schema:
                type: string
                example: public, max-age=30
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SearchResponse"
              examples:
                nonDoppler:
                  summary: Non-Doppler lookup
                  value:
                    market_hash_name: AK-47 | Redline (Field-Tested)
                    is_doppler: false
                    search_variants:
                      - AK-47 | Redline (Field-Tested)
                    data:
                      youpin:
                        id: 210
                        market_hash_name: AK-47 | Redline (Field-Tested)
                        stattrak: 0
                        souvenir: 0
                        price_rmb: "142.00"
                        change_24h: "0.30"
                        change_7d: "1.10"
                        change_30d: "-0.80"
                        change_90d: "4.20"
                        avg_7d: "141.20"
                        avg_30d: "143.80"
                        avg_90d: "136.00"
                        count: 612
                        phase: ""
                        updated_at: 2026-04-21T12:06:35.000Z
                        youpin_template_id: 1021
                        liquidity: "8.90"
                      buff163:
                        id: 62235
                        market_hash_name: AK-47 | Redline (Field-Tested)
                        stattrak: 0
                        souvenir: 0
                        exterior: Field-Tested
                        price: "138.80"
                        change_24h: "0.10"
                        change_7d: "0.90"
                        change_30d: "-1.10"
                        change_90d: "3.80"
                        avg_7d: "138.20"
                        avg_30d: "140.10"
                        avg_90d: "133.50"
                        count: 1203
                        updated_at: 2026-04-21T12:20:00.000Z
                        item_page_url: https://buff.163.com/goods/35247
                        liquidity: "9.10"
                      c5game: null
                      ecosteam: null
                      skinbaron:
                        id: 18
                        market_hash_name: AK-47 | Redline (Field-Tested)
                        stattrak: 0
                        souvenir: 0
                        exterior: Field-Tested
                        price: "17.90"
                        change_24h: "-0.20"
                        change_7d: "0.80"
                        change_30d: "-1.40"
                        change_90d: "2.90"
                        avg_7d: "17.85"
                        avg_30d: "18.10"
                        avg_90d: "17.40"
                        count: 240
                        updated_at: 2026-04-21T12:17:00.000Z
                        item_page_url: https://skinbaron.de/en/csgo/ak-47-redline-field-tested
                        liquidity: "9.00"
                      skinport:
                        id: 77
                        market_hash_name: AK-47 | Redline (Field-Tested)
                        item_page_url: https://skinport.com/item/ak-47-redline-field-tested
                        stattrak: 0
                        souvenir: 0
                        exterior: Field-Tested
                        price: "18.20"
                        change_24h: "0.00"
                        change_7d: "0.90"
                        change_30d: "-1.20"
                        change_90d: "3.30"
                        avg_7d: "18.10"
                        avg_30d: "18.30"
                        avg_90d: "17.60"
                        count: 378
                        updated_at: 2026-04-21T12:16:00.000Z
                        liquidity: "9.20"
                      market_csgo:
                        id: 4412
                        market_hash_name: AK-47 | Redline (Field-Tested)
                        item_page_url: https://market.csgo.com/en/item/4412/AK-47-Redline-Field-Tested
                        stattrak: 0
                        souvenir: 0
                        exterior: Field-Tested
                        price: "19.45"
                        change_24h: "0.10"
                        change_7d: "0.70"
                        change_30d: "-0.90"
                        change_90d: "3.60"
                        avg_7d: "19.30"
                        avg_30d: "19.60"
                        avg_90d: "18.80"
                        count: 980
                        sales7: 142
                        updated_at: 2026-04-21T12:13:16.000Z
                        liquidity: "9.30"
                      csfloat:
                        id: 501
                        market_hash_name: AK-47 | Redline (Field-Tested)
                        stattrak: 0
                        souvenir: 0
                        exterior: Field-Tested
                        price: "18.75"
                        change_24h: "0.20"
                        change_7d: "0.90"
                        change_30d: "-1.10"
                        change_90d: "3.40"
                        avg_7d: "18.60"
                        avg_30d: "19.00"
                        avg_90d: "18.10"
                        count: 320
                        updated_at: 2026-04-21T12:18:00.000Z
                        item_page_url: https://csfloat.com/item/123456789
                        buff_template_id: 35247
                        liquidity: "9.10"
                      lisskins:
                        id: 701
                        market_hash_name: AK-47 | Redline (Field-Tested)
                        stattrak: 0
                        souvenir: 0
                        exterior: Field-Tested
                        price: "17.90"
                        change_24h: "0.10"
                        change_7d: "0.50"
                        change_30d: "-0.80"
                        change_90d: "2.10"
                        avg_7d: "17.70"
                        avg_30d: "18.20"
                        avg_90d: "17.40"
                        count: 280
                        updated_at: 2026-04-21T12:18:30.000Z
                        item_page_url: https://lis-skins.com/market/csgo/ak-47-redline-field-tested/
                        buff_template_id: 35247
                        liquidity: "9.10"
                      dmarket:
                        id: 801
                        market_hash_name: AK-47 | Redline (Field-Tested)
                        stattrak: 0
                        souvenir: 0
                        exterior: Field-Tested
                        price: "18.20"
                        change_24h: "0.15"
                        change_7d: "0.60"
                        change_30d: "-0.70"
                        change_90d: "2.30"
                        avg_7d: "18.00"
                        avg_30d: "18.40"
                        avg_90d: "17.80"
                        count: 310
                        updated_at: 2026-04-21T12:18:45.000Z
                        item_page_url: https://dmarket.com/ingame-items/item-list/csgo-skins
                        buff_template_id: 35247
                        liquidity: "9.10"
                    requestor: customer@example.com
                    plan: pro
                    timestamp: 2026-04-21T12:20:40.000Z
                doppler:
                  summary: Doppler lookup (all phases)
                  value:
                    market_hash_name: Glock-18 | Gamma Doppler (Factory New)
                    is_doppler: true
                    search_variants:
                      - Glock-18 | Gamma Doppler (Factory New) (Emerald)
                      - Glock-18 | Gamma Doppler (Factory New) (Phase 1)
                      - Glock-18 | Gamma Doppler (Factory New) (Phase 2)
                      - Glock-18 | Gamma Doppler (Factory New) (Phase 3)
                      - Glock-18 | Gamma Doppler (Factory New) (Phase 4)
                    data:
                      youpin:
                        - id: 30155
                          market_hash_name: Glock-18 | Gamma Doppler (Factory New) (Emerald)
                          stattrak: 0
                          souvenir: 0
                          price_rmb: "7333.0000"
                          change_24h: "-1.40"
                          change_7d: "-1.63"
                          change_30d: "-7.67"
                          change_90d: "-15.60"
                          avg_7d: "7331.46"
                          avg_30d: "7513.31"
                          avg_90d: "7788.60"
                          count: 8
                          phase: Emerald
                          updated_at: 2026-04-21T12:06:35.000Z
                          youpin_template_id: 57643
                          liquidity: "2.10"
                        - id: 30156
                          market_hash_name: Glock-18 | Gamma Doppler (Factory New) (Phase 2)
                          stattrak: 0
                          souvenir: 0
                          price_rmb: "1320.0000"
                          change_24h: "-0.90"
                          change_7d: "1.20"
                          change_30d: "-3.40"
                          change_90d: "8.90"
                          avg_7d: "1320.10"
                          avg_30d: "1378.55"
                          avg_90d: "1250.00"
                          count: 42
                          phase: Phase 2
                          updated_at: 2026-04-21T12:06:35.000Z
                          youpin_template_id: 57912
                          liquidity: "5.40"
                      buff163: []
                      c5game: []
                      ecosteam: []
                      skinbaron: []
                      skinport: []
                      market_csgo: []
                      csfloat: []
                      lisskins: []
                      dmarket: []
                    requestor: customer@example.com
                    plan: pro
                    timestamp: 2026-04-21T12:20:45.000Z
        "400":
          description: Missing or invalid query parameter.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                missingParam:
                  value:
                    error: "Missing parameter: market_hash_name"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
  /v1/market-sales/search:
    get:
      tags:
        - Sales Data
      summary: Look up sales by market_hash_name (Enterprise)
      description: |
        Returns historical marketplace **sales** for up to **5**
        `market_hash_name` values, including nested `stickers` and `keychains` per sale.

        At most **50** most recent sales are returned **per** `market_hash_name`
        (so up to 250 rows when querying 5 names). Results are ordered by
        `sold_at` descending.

        Pass one or more names via repeated query params or a comma-separated list:

        ```
        ?market_hash_name=AK-47 | Redline (Field-Tested)
        ?market_hash_name=AK-47 | Redline (Field-Tested)&market_hash_name=M4A4 | Temukau (Minimal Wear)
        ?market_hash_name=AK-47 | Redline (Field-Tested),M4A4 | Temukau (Minimal Wear)
        ```

        Optional filters:

        - `marketplace`: `csfloat`, `youpin`, `skinport`
        - `float_min`, `float_max`: float range (inclusive)
        - `paint_index`: one or more paint indexes
        - `paint_seed`: one or more paint seeds / patterns
        - `price_min`, `price_max`: sale price range in **cents**

        `price` and `reference_price` are in **cents**. `sale_id`, `sticker_id` and
        `keychain_id` are returned as **strings** to avoid precision loss.
      operationId: searchMarketSales
      parameters:
        - name: market_hash_name
          in: query
          required: true
          description: |
            Steam `market_hash_name` to look up. Repeat up to 5 times, or pass a
            comma-separated list (max 5 unique names).
          schema:
            type: array
            minItems: 1
            maxItems: 5
            items:
              type: string
              minLength: 1
          style: form
          explode: true
          examples:
            single:
              value:
                - AK-47 | Redline (Field-Tested)
            multiple:
              value:
                - AK-47 | Redline (Field-Tested)
                - M4A4 | Temukau (Minimal Wear)
        - name: marketplace
          in: query
          required: false
          schema:
            type: string
            enum:
              - csfloat
              - youpin
              - skinport
        - name: float_min
          in: query
          required: false
          schema:
            type: number
          description: Minimum `float_value` (inclusive).
        - name: float_max
          in: query
          required: false
          schema:
            type: number
          description: Maximum `float_value` (inclusive).
        - name: paint_index
          in: query
          required: false
          description: |
            Paint index filter. Repeat the parameter or pass a comma-separated list.
          schema:
            type: array
            items:
              type: integer
          style: form
          explode: true
        - name: paint_seed
          in: query
          required: false
          description: |
            Paint seed / pattern filter. Repeat the parameter or pass a comma-separated list.
          schema:
            type: array
            items:
              type: integer
          style: form
          explode: true
        - name: price_min
          in: query
          required: false
          schema:
            type: integer
          description: Minimum sale price in cents (inclusive).
        - name: price_max
          in: query
          required: false
          schema:
            type: integer
          description: Maximum sale price in cents (inclusive).
      responses:
        "200":
          description: Matching sales with nested stickers and keychains.
          headers:
            Cache-Control:
              schema:
                type: string
                example: public, max-age=60
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MarketSalesSearchResponse"
        "400":
          description: Missing or invalid parameters.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
  /v1/market-sales/export:
    get:
      tags:
        - Sales Data
      summary: ZIP export of the last 24 hours (Enterprise)
      description: |
        Returns a **ZIP archive** (`market-sales-export.zip`) with three CSV files
        for subscription customers who replicate the dataset locally once per day.

        | File in ZIP | Contents | Typical row count |
        |-------------|------------------|-------------------|
        | `sales.csv` | Sale events | ~100k / 24h |
        | `stickers.csv` | Stickers attached to sales | ~60k / 24h |
        | `keychains.csv` | Keychains attached to sales | ~1k / 24h |

        Always exports **all rows from the last 24 hours**
        in a single request (~6 MB compressed ZIP). No pagination.

        Join the CSVs locally on `(marketplace, sale_id, sold_at)`.


        Requires `x-api-key`. The key must include `/v1/market-sales/export` in its
        `allowed_endpoints` (or `*`).


        ```bash
        curl -H "x-api-key: YOUR_KEY" \
          "https://api.cspriceapi.com/v1/market-sales/export" \
          -o market-sales-export.zip
        unzip market-sales-export.zip
        ```


        See component schemas `MarketSalesCsvSalesRow`, `MarketSalesCsvStickersRow`
        and `MarketSalesCsvKeychainsRow` for the exact column layout.

        **Notes**

        - `price` and `reference_price` are in **cents** (integer).
        - `sale_id`, `sticker_id`, `keychain_id` are large integers serialized as
          **strings** in CSV to avoid JavaScript precision loss.
        - `marketplace` values: `csfloat`, `youpin`, `skinport`.
      operationId: exportMarketSalesZip
      responses:
        "200":
          description: |
            ZIP archive containing `sales.csv`, `stickers.csv` and `keychains.csv`
            (each with a header row). Row counts are also exposed via response headers.
          headers:
            Cache-Control:
              schema:
                type: string
                example: private, no-store
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="market-sales-export.zip"
            X-Sales-Row-Count:
              schema:
                type: integer
                example: 97596
              description: Data rows in `sales.csv` (excludes header).
            X-Sticker-Row-Count:
              schema:
                type: integer
                example: 61007
            X-Keychain-Row-Count:
              schema:
                type: integer
                example: 1228
            X-Window-Hours:
              schema:
                type: integer
                example: 24
            X-Window-Start:
              schema:
                type: string
                format: date-time
              description: Start of the export window (UTC).
            X-Window-End:
              schema:
                type: string
                format: date-time
              description: Time the export was generated (UTC).
          content:
            application/zip:
              schema:
                type: string
                format: binary
              example: (binary ZIP – see CSV schemas for contained file layout)
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: |
        API key issued per customer. Send it in the `x-api-key` header on every
        request. Keys can be plan-scoped (per-minute and per-day rate limits)
        and endpoint-scoped (ACL). Inactive or expired keys will be rejected
        with `401`.
  parameters:
    MarketHashNameQuery:
      name: market_hash_name
      in: query
      required: true
      description: |
        Steam `market_hash_name` of the skin to look up. For Dopplers /
        Gamma Dopplers the phase suffix is optional – it will be stripped and
        every phase variant will be queried.
      schema:
        type: string
        minLength: 1
      examples:
        nonDoppler:
          value: AK-47 | Redline (Field-Tested)
        doppler:
          value: Glock-18 | Gamma Doppler (Factory New)
  responses:
    BadRequest:
      description: Invalid or missing parameter.
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
              markets:
                type: array
                items:
                  type: string
                description: Allowed marketplace slugs (when relevant).
    Unauthorized:
      description: Missing, invalid, disabled or expired API key.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            missing:
              value:
                error: Missing API key
            invalid:
              value:
                error: Invalid API key
            disabled:
              value:
                error: API key disabled
            expired:
              value:
                error: API key expired
    Forbidden:
      description: The API key is valid but is not allowed to call this endpoint (endpoint ACL).
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            acl:
              value:
                error: Endpoint not allowed for this API key
    RateLimited:
      description: Per-minute or per-day rate limit exceeded.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            perMinute:
              value:
                error: Rate limit exceeded (per minute)
            perDay:
              value:
                error: Daily limit exceeded
    InternalError:
      description: Internal server error – temporary upstream failure, etc.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            generic:
              value:
                error: Internal server error
            db:
              value:
                error: DB error
  schemas:
    DecimalString:
      type: string
      description: |
        Fixed-point decimal value serialized as a string (preserves precision
        across languages). Parse with an arbitrary-precision decimal library;
        do **not** parse as a native float.
      pattern: ^-?\d+(\.\d+)?$
      example: "1234.5600"
    TinyBool:
      type: integer
      enum:
        - 0
        - 1
      nullable: true
      description: Boolean stored as `tinyint(1)`; `0` = false, `1` = true.
      example: 0
    Exterior:
      type: string
      nullable: true
      description: |
        Exterior (wear) of the skin. Typical values: `Factory New`,
        `Minimal Wear`, `Field-Tested`, `Well-Worn`, `Battle-Scarred`.
        Casing may vary between sources (e.g. Buff163 uses `"Factory new"`).
      example: Field-Tested
    Phase:
      type: string
      nullable: true
      description: |
        Doppler phase, normalised to English. Empty string or `null` for
        non-phase items.
      example: Phase 2
    UpdatedAt:
      type: string
      format: date-time
      description: ISO-8601 UTC timestamp (millisecond precision).
      example: 2026-04-21T12:06:35.000Z
    BaseWrapper:
      type: object
      description: Envelope fields returned by every `GET /v1/prices/*` response.
      properties:
        source:
          type: string
          description: Human-readable marketplace identifier.
        requestor:
          type: string
          format: email
          description: Email address associated with the API key making the call.
          example: customer@example.com
        plan:
          type: string
          description: Plan of the API key (e.g. `free`, `pro`, `enterprise`).
          example: pro
        timestamp:
          allOf:
            - $ref: "#/components/schemas/UpdatedAt"
          description: Server time when this response was produced.
      required:
        - source
        - timestamp
    YoupinItem:
      type: object
      description: Current YouPin listing price row, including liquidity when available.
      properties:
        id:
          type: integer
          example: 30155
        market_hash_name:
          type: string
          example: ★ Hand Wraps | Spruce DDPAT (Factory New)
        stattrak:
          $ref: "#/components/schemas/TinyBool"
        souvenir:
          $ref: "#/components/schemas/TinyBool"
        price_rmb:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Lowest current listing price on YouPin, in CNY (RMB).
          example: "7333.0000"
        change_24h:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: 24h price change in percent.
          example: "-1.40"
        change_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "-1.63"
        change_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "-7.67"
        change_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "-15.60"
        avg_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "7331.46"
        avg_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "7513.31"
        avg_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "7788.60"
        count:
          type: integer
          nullable: true
          description: Number of active listings.
          example: 8
        phase:
          $ref: "#/components/schemas/Phase"
        updated_at:
          $ref: "#/components/schemas/UpdatedAt"
        youpin_template_id:
          type: integer
          nullable: true
          description: YouPin internal template id.
          example: 57643
        liquidity:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Internal liquidity score (0.00 – 10.00). `null` if the skin is not in the internal catalog.
          example: "12.16"
      required:
        - id
        - market_hash_name
        - updated_at
    YoupinBuyorderItem:
      type: object
      description: Current YouPin buy-order row.
      properties:
        id:
          type: integer
          example: 1
        market_hash_name:
          type: string
          example: Glock-18 | Gamma Doppler (Factory New) (Phase 2)
        templateId:
          type: integer
          nullable: true
          example: 57912
        buyorder_price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Highest standing buy-order price (CNY / RMB).
          example: "1122.50"
        blue_buyorder_price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Highest "blue"-tier buy-order price (CNY / RMB), used e.g. for certain Doppler phases.
          example: "980.00"
        phase:
          $ref: "#/components/schemas/Phase"
        typeId:
          type: integer
          nullable: true
          example: 42
        updated_at:
          $ref: "#/components/schemas/UpdatedAt"
        count:
          type: integer
          nullable: true
          example: 36
      required:
        - id
        - market_hash_name
    Buff163Item:
      type: object
      description: Current Buff163 listing price row, including liquidity when available.
      properties:
        id:
          type: integer
          example: 62235
        market_hash_name:
          type: string
          example: Glock-18 | Gamma Doppler (Factory New)
        stattrak:
          $ref: "#/components/schemas/TinyBool"
        souvenir:
          $ref: "#/components/schemas/TinyBool"
        exterior:
          $ref: "#/components/schemas/Exterior"
        price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Lowest current listing price on Buff163, in CNY (RMB).
          example: "1333.50"
        change_24h:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        count:
          type: integer
          nullable: true
          example: 586
        updated_at:
          $ref: "#/components/schemas/UpdatedAt"
        item_page_url:
          type: string
          format: uri
          nullable: true
          example: https://buff.163.com/goods/776015
        liquidity:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "8.70"
      required:
        - id
        - market_hash_name
        - updated_at
    C5GameItem:
      type: object
      description: Current C5Game listing price row, including liquidity when available.
      properties:
        id:
          type: integer
          example: 10
        market_hash_name:
          type: string
          example: AK-47 | Redline (Field-Tested)
        item_page_url:
          type: string
          format: uri
          nullable: true
          example: https://www.c5game.com/en/csgo/product/123456
        stattrak:
          $ref: "#/components/schemas/TinyBool"
        souvenir:
          $ref: "#/components/schemas/TinyBool"
        exterior:
          $ref: "#/components/schemas/Exterior"
        price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Lowest current listing price on C5Game, in CNY (RMB).
          example: "138.20"
        change_24h:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        count:
          type: integer
          nullable: true
          example: 241
        updated_at:
          $ref: "#/components/schemas/UpdatedAt"
        liquidity:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "7.40"
      required:
        - id
        - market_hash_name
        - updated_at
    EcoSteamItem:
      type: object
      description: Current EcoSteam listing price row, including liquidity when available.
      properties:
        id:
          type: integer
          example: 5
        market_hash_name:
          type: string
          example: AWP | Dragon Lore (Field-Tested)
        item_page_url:
          type: string
          format: uri
          nullable: true
          example: https://www.ecosteam.cn/item/12345
        stattrak:
          $ref: "#/components/schemas/TinyBool"
        souvenir:
          $ref: "#/components/schemas/TinyBool"
        exterior:
          $ref: "#/components/schemas/Exterior"
        price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Lowest current listing price on EcoSteam, in CNY (RMB).
          example: "91200.00"
        change_24h:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        count:
          type: integer
          nullable: true
          example: 3
        updated_at:
          $ref: "#/components/schemas/UpdatedAt"
        liquidity:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "1.20"
      required:
        - id
        - market_hash_name
        - updated_at
    SkinBaronItem:
      type: object
      description: Current SkinBaron listing price row, including liquidity when available.
      properties:
        id:
          type: integer
          example: 42
        market_hash_name:
          type: string
          example: ★ Karambit | Fade (Factory New)
        stattrak:
          $ref: "#/components/schemas/TinyBool"
        souvenir:
          $ref: "#/components/schemas/TinyBool"
        exterior:
          $ref: "#/components/schemas/Exterior"
        price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Lowest current listing price on SkinBaron, in EUR.
          example: "2899.00"
        change_24h:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        count:
          type: integer
          nullable: true
          example: 9
        updated_at:
          $ref: "#/components/schemas/UpdatedAt"
        item_page_url:
          type: string
          format: uri
          nullable: true
          example: https://skinbaron.de/en/csgo/karambit-fade-factory-new
        liquidity:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "4.10"
      required:
        - id
        - market_hash_name
        - updated_at
    SkinportItem:
      type: object
      description: Current Skinport listing price row, including liquidity when available.
      properties:
        id:
          type: integer
          example: 101
        market_hash_name:
          type: string
          example: AK-47 | Asiimov (Field-Tested)
        item_page_url:
          type: string
          format: uri
          nullable: true
          example: https://skinport.com/item/ak-47-asiimov-field-tested
        stattrak:
          $ref: "#/components/schemas/TinyBool"
        souvenir:
          $ref: "#/components/schemas/TinyBool"
        exterior:
          $ref: "#/components/schemas/Exterior"
        price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Lowest current listing price on Skinport, in EUR.
          example: "68.40"
        change_24h:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        count:
          type: integer
          nullable: true
          example: 412
        updated_at:
          $ref: "#/components/schemas/UpdatedAt"
        liquidity:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "9.20"
      required:
        - id
        - market_hash_name
        - updated_at
    CsfloatItem:
      type: object
      description: Current CSFloat listing price row, including liquidity when available.
      properties:
        id:
          type: integer
          example: 501
        market_hash_name:
          type: string
          example: AK-47 | Redline (Field-Tested)
        stattrak:
          $ref: "#/components/schemas/TinyBool"
        souvenir:
          $ref: "#/components/schemas/TinyBool"
        exterior:
          $ref: "#/components/schemas/Exterior"
        price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Lowest current listing price on CSFloat, in USD.
          example: "18.75"
        change_24h:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        count:
          type: integer
          nullable: true
          example: 320
        updated_at:
          $ref: "#/components/schemas/UpdatedAt"
        item_page_url:
          type: string
          format: uri
          nullable: true
          example: https://csfloat.com/item/123456789
        buff_template_id:
          type: integer
          nullable: true
          example: 35247
        liquidity:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "9.10"
      required:
        - id
        - market_hash_name
        - updated_at
    LisskinsItem:
      type: object
      description: Current Lisskins listing price row, including liquidity when available.
      properties:
        id:
          type: integer
          example: 701
        market_hash_name:
          type: string
          example: AK-47 | Redline (Field-Tested)
        stattrak:
          $ref: "#/components/schemas/TinyBool"
        souvenir:
          $ref: "#/components/schemas/TinyBool"
        exterior:
          $ref: "#/components/schemas/Exterior"
        price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Lowest current listing price on Lisskins, in USD.
          example: "17.90"
        change_24h:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        count:
          type: integer
          nullable: true
          example: 280
        updated_at:
          $ref: "#/components/schemas/UpdatedAt"
        item_page_url:
          type: string
          format: uri
          nullable: true
          example: https://lis-skins.com/market/csgo/ak-47-redline-field-tested/
        buff_template_id:
          type: integer
          nullable: true
          example: 35247
        liquidity:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "9.10"
      required:
        - id
        - market_hash_name
        - updated_at
    DmarketItem:
      type: object
      description: Current DMarket listing price row, including liquidity when available.
      properties:
        id:
          type: integer
          example: 801
        market_hash_name:
          type: string
          example: AK-47 | Redline (Field-Tested)
        stattrak:
          $ref: "#/components/schemas/TinyBool"
        souvenir:
          $ref: "#/components/schemas/TinyBool"
        exterior:
          $ref: "#/components/schemas/Exterior"
        price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Lowest current listing price on DMarket, in USD.
          example: "18.20"
        change_24h:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        count:
          type: integer
          nullable: true
          example: 310
        updated_at:
          $ref: "#/components/schemas/UpdatedAt"
        item_page_url:
          type: string
          format: uri
          nullable: true
          example: https://dmarket.com/ingame-items/item-list/csgo-skins
        buff_template_id:
          type: integer
          nullable: true
          example: 35247
        liquidity:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "9.10"
      required:
        - id
        - market_hash_name
        - updated_at
    ShadowpayItem:
      type: object
      description: Current ShadowPay listing price row, including liquidity when available.
      properties:
        id:
          type: integer
          example: 2
        market_hash_name:
          type: string
          example: ★ Bayonet | Marble Fade (Minimal Wear)
        stattrak:
          $ref: "#/components/schemas/TinyBool"
        souvenir:
          $ref: "#/components/schemas/TinyBool"
        exterior:
          $ref: "#/components/schemas/Exterior"
        price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Lowest current listing price on ShadowPay, in USD.
          example: "450.65"
        change_24h:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        count:
          type: integer
          nullable: true
          example: 10
        updated_at:
          $ref: "#/components/schemas/UpdatedAt"
        item_page_url:
          type: string
          format: uri
          nullable: true
          example: https://shadowpay.com/en?search=Bayonet
        liquidity:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "8.50"
      required:
        - id
        - market_hash_name
        - updated_at
    WaxpeerItem:
      type: object
      description: Current Waxpeer listing price row, including liquidity when available.
      properties:
        id:
          type: integer
          example: 2
        market_hash_name:
          type: string
          example: SCAR-20 | Caged (Factory New)
        stattrak:
          $ref: "#/components/schemas/TinyBool"
        souvenir:
          $ref: "#/components/schemas/TinyBool"
        exterior:
          $ref: "#/components/schemas/Exterior"
        price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Lowest current listing price on Waxpeer, in USD.
          example: "0.92"
        change_24h:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        count:
          type: integer
          nullable: true
          example: 13
        updated_at:
          $ref: "#/components/schemas/UpdatedAt"
        item_page_url:
          type: string
          format: uri
          nullable: true
          example: https://waxpeer.com/?game=csgo&search=SCAR-20
        liquidity:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "7.20"
      required:
        - id
        - market_hash_name
        - updated_at
    SteamItem:
      type: object
      description: |
        Current Steam Community Market listing snapshot. Includes Steam-specific
        field `currency` and liquidity when available.
      properties:
        id:
          type: integer
          example: 1
        market_hash_name:
          type: string
          example: AK-47 | Redline (Field-Tested)
        stattrak:
          $ref: "#/components/schemas/TinyBool"
        souvenir:
          $ref: "#/components/schemas/TinyBool"
        exterior:
          $ref: "#/components/schemas/Exterior"
        price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Current Steam Market lowest price.
          example: "36.83"
        count:
          type: integer
          nullable: true
          example: 120
        currency:
          type: integer
          description: Steam currency id (e.g. `1` = USD, `3` = EUR).
          example: 1
        item_page_url:
          type: string
          format: uri
          nullable: true
          example: https://steamcommunity.com/market/listings/730/AK-47%20%7C%20Redline%20(Field-Tested)
        updated_at:
          $ref: "#/components/schemas/UpdatedAt"
        liquidity:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "10.20"
      required:
        - id
        - market_hash_name
        - currency
        - updated_at
    MarketCsgoItem:
      type: object
      description: Current Market.CSGO listing price row, including liquidity when available.
      properties:
        id:
          type: integer
          example: 1
        market_hash_name:
          type: string
          example: Sticker | BLAST.tv | Paris 2023
        item_page_url:
          type: string
          format: uri
          nullable: true
          example: https://market.csgo.com/en/item/123/Sticker-BLAST.tv-Paris-2023
        stattrak:
          $ref: "#/components/schemas/TinyBool"
        souvenir:
          $ref: "#/components/schemas/TinyBool"
        exterior:
          $ref: "#/components/schemas/Exterior"
        price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Lowest current listing price on Market.CSGO, in USD.
          example: "0.01"
        change_24h:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        change_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_7d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_30d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        avg_90d:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
        count:
          type: integer
          nullable: true
          example: 5823
        sales7:
          type: integer
          nullable: true
          description: Number of sales over the last 7 days.
          example: 214
        updated_at:
          $ref: "#/components/schemas/UpdatedAt"
        liquidity:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "9.80"
      required:
        - id
        - market_hash_name
        - updated_at
    FloatRangedV2Item:
      type: object
      description: Float-range filtered listing snapshot (v2).
      properties:
        market_hash_name:
          type: string
          example: Glock-18 | Gamma Doppler (Factory New)
        float_range:
          type: string
          description: Float-range bucket/filter.
          example: 0.00-0.07
        phase:
          $ref: "#/components/schemas/Phase"
        fade:
          type: number
          nullable: true
          description: |
            Fade percentage for Fade skins (e.g. `81.7`). `null` for non-Fade
            items.
          example: 81.7
        count:
          type: integer
          nullable: true
          example: 12
        price_rmb:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          description: Lowest listing price in CNY (RMB) for this float range.
          example: "1230.0000"
        updated_at:
          $ref: "#/components/schemas/UpdatedAt"
      required:
        - market_hash_name
        - float_range
        - phase
        - updated_at
    LatestItemError:
      type: object
      properties:
        market_hash_name:
          type: string
        code:
          type: string
          enum:
            - not_found
      required:
        - market_hash_name
        - code
    LatestItem:
      type: object
      description: |
        One skin with nested marketplace objects. Only marketplaces that have
        data for this skin are present (sparse). Nested objects use the same
        field shapes as the legacy per-market listing responses
        (`YoupinItem`, `Buff163Item`, `SteamItem`, …).
      properties:
        market_hash_name:
          type: string
        youpin:
          allOf:
            - $ref: "#/components/schemas/YoupinItem"
          nullable: true
        buff163:
          allOf:
            - $ref: "#/components/schemas/Buff163Item"
          nullable: true
        c5game:
          allOf:
            - $ref: "#/components/schemas/C5GameItem"
          nullable: true
        ecosteam:
          allOf:
            - $ref: "#/components/schemas/EcoSteamItem"
          nullable: true
        skinbaron:
          allOf:
            - $ref: "#/components/schemas/SkinBaronItem"
          nullable: true
        skinport:
          allOf:
            - $ref: "#/components/schemas/SkinportItem"
          nullable: true
        csfloat:
          allOf:
            - $ref: "#/components/schemas/CsfloatItem"
          nullable: true
        lisskins:
          allOf:
            - $ref: "#/components/schemas/LisskinsItem"
          nullable: true
        dmarket:
          allOf:
            - $ref: "#/components/schemas/DmarketItem"
          nullable: true
        shadowpay:
          allOf:
            - $ref: "#/components/schemas/ShadowpayItem"
          nullable: true
        waxpeer:
          allOf:
            - $ref: "#/components/schemas/WaxpeerItem"
          nullable: true
        steam:
          allOf:
            - $ref: "#/components/schemas/SteamItem"
          nullable: true
        market-csgo:
          allOf:
            - $ref: "#/components/schemas/MarketCsgoItem"
          nullable: true
      required:
        - market_hash_name
      additionalProperties: true
    LatestPricesResponse:
      type: object
      description: Item-centric latest listing snapshot.
      properties:
        items:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/LatestItem"
          description: Map of market_hash_name → nested marketplace prices.
        markets:
          type: array
          items:
            type: string
          description: Marketplaces included in this response (after filtering).
        requestor:
          type: string
          format: email
        plan:
          type: string
        timestamp:
          $ref: "#/components/schemas/UpdatedAt"
        errors:
          type: array
          items:
            $ref: "#/components/schemas/LatestItemError"
          description: Present on POST when some requested items were missing.
      required:
        - items
        - markets
        - timestamp
    YoupinPricesResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: "#/components/schemas/YoupinItem"
            source:
              type: string
              enum:
                - YouPin
          required:
            - data
    YoupinBuyorderResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: "#/components/schemas/YoupinBuyorderItem"
            source:
              type: string
              enum:
                - YouPin
          required:
            - data
    Buff163PricesResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: "#/components/schemas/Buff163Item"
            source:
              type: string
              enum:
                - Buff163
          required:
            - data
    C5GamePricesResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: "#/components/schemas/C5GameItem"
            source:
              type: string
              enum:
                - C5Game
          required:
            - data
    EcoSteamPricesResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: "#/components/schemas/EcoSteamItem"
            source:
              type: string
              enum:
                - EcoSteam
          required:
            - data
    SkinBaronPricesResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: "#/components/schemas/SkinBaronItem"
            source:
              type: string
              enum:
                - SkinBaron
          required:
            - data
    SkinportPricesResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: "#/components/schemas/SkinportItem"
            source:
              type: string
              enum:
                - Skinport
          required:
            - data
    MarketCsgoPricesResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: "#/components/schemas/MarketCsgoItem"
            source:
              type: string
              enum:
                - Market CSGO
          required:
            - data
    CsfloatPricesResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: "#/components/schemas/CsfloatItem"
            source:
              type: string
              enum:
                - CSFloat
          required:
            - data
    LisskinsPricesResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: "#/components/schemas/LisskinsItem"
            source:
              type: string
              enum:
                - Lisskins
          required:
            - data
    DmarketPricesResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: "#/components/schemas/DmarketItem"
            source:
              type: string
              enum:
                - DMarket
          required:
            - data
    ShadowpayPricesResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: "#/components/schemas/ShadowpayItem"
            source:
              type: string
              enum:
                - ShadowPay
          required:
            - data
    WaxpeerPricesResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: "#/components/schemas/WaxpeerItem"
            source:
              type: string
              enum:
                - Waxpeer
          required:
            - data
    SteamPricesResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: "#/components/schemas/SteamItem"
            source:
              type: string
              enum:
                - Steam
          required:
            - data
    PriceHistoryPointDaily:
      type: object
      properties:
        day:
          type: string
          format: date
          example: 2026-08-20
        price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "186.2000"
        count:
          type: integer
          nullable: true
          example: 11404
      required:
        - day
    PriceHistoryPointHourly:
      type: object
      properties:
        day:
          type: string
          format: date
          example: 2026-08-20
        slot:
          type: integer
          description: Hourly bucket index within the day (0–23).
          example: 10
        last_ts:
          type: string
          example: 2026-08-20 10:15:00
        price:
          allOf:
            - $ref: "#/components/schemas/DecimalString"
          nullable: true
          example: "186.2000"
        count:
          type: integer
          nullable: true
          example: 11404
      required:
        - day
        - slot
    PriceHistoryResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            market:
              type: string
              example: youpin
            market_hash_name:
              type: string
              example: AK-47 | Redline (Field-Tested)
            resolution:
              type: string
              enum:
                - hourly
                - daily
            currency:
              type: string
              enum:
                - CNY
                - EUR
                - USD
            from:
              type: string
              format: date
            to:
              type: string
              format: date
            count:
              type: integer
              example: 365
            data:
              type: array
              items:
                oneOf:
                  - $ref: "#/components/schemas/PriceHistoryPointDaily"
                  - $ref: "#/components/schemas/PriceHistoryPointHourly"
            source:
              type: string
              example: YouPin History
          required:
            - market
            - market_hash_name
            - resolution
            - currency
            - from
            - to
            - count
            - data
    FloatRangedV2PricesResponse:
      allOf:
        - $ref: "#/components/schemas/BaseWrapper"
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: "#/components/schemas/FloatRangedV2Item"
            source:
              type: string
              enum:
                - Float Ranged
          required:
            - data
    SearchDataNonDoppler:
      type: object
      description: |
        Per-marketplace lookup results. Each key is either a single item
        object (the skin was found on that marketplace) or `null` (not found).
      properties:
        youpin:
          oneOf:
            - $ref: "#/components/schemas/YoupinItem"
          nullable: true
        buff163:
          oneOf:
            - $ref: "#/components/schemas/Buff163Item"
          nullable: true
        c5game:
          oneOf:
            - $ref: "#/components/schemas/C5GameItem"
          nullable: true
        ecosteam:
          oneOf:
            - $ref: "#/components/schemas/EcoSteamItem"
          nullable: true
        skinbaron:
          oneOf:
            - $ref: "#/components/schemas/SkinBaronItem"
          nullable: true
        skinport:
          oneOf:
            - $ref: "#/components/schemas/SkinportItem"
          nullable: true
        market_csgo:
          oneOf:
            - $ref: "#/components/schemas/MarketCsgoItem"
          nullable: true
        csfloat:
          oneOf:
            - $ref: "#/components/schemas/CsfloatItem"
          nullable: true
        lisskins:
          oneOf:
            - $ref: "#/components/schemas/LisskinsItem"
          nullable: true
        dmarket:
          oneOf:
            - $ref: "#/components/schemas/DmarketItem"
          nullable: true
        shadowpay:
          oneOf:
            - $ref: "#/components/schemas/ShadowpayItem"
          nullable: true
        waxpeer:
          oneOf:
            - $ref: "#/components/schemas/WaxpeerItem"
          nullable: true
        steam:
          oneOf:
            - $ref: "#/components/schemas/SteamItem"
          nullable: true
      required:
        - youpin
        - buff163
        - c5game
        - ecosteam
        - skinbaron
        - skinport
        - market_csgo
        - csfloat
        - lisskins
        - dmarket
        - shadowpay
        - waxpeer
        - steam
    SearchDataDoppler:
      type: object
      description: |
        Per-marketplace lookup results for Doppler skins. Each key is an
        **array** containing every phase variant found (possibly empty).
      properties:
        youpin:
          type: array
          items:
            $ref: "#/components/schemas/YoupinItem"
        buff163:
          type: array
          items:
            $ref: "#/components/schemas/Buff163Item"
        c5game:
          type: array
          items:
            $ref: "#/components/schemas/C5GameItem"
        ecosteam:
          type: array
          items:
            $ref: "#/components/schemas/EcoSteamItem"
        skinbaron:
          type: array
          items:
            $ref: "#/components/schemas/SkinBaronItem"
        skinport:
          type: array
          items:
            $ref: "#/components/schemas/SkinportItem"
        market_csgo:
          type: array
          items:
            $ref: "#/components/schemas/MarketCsgoItem"
        csfloat:
          type: array
          items:
            $ref: "#/components/schemas/CsfloatItem"
        lisskins:
          type: array
          items:
            $ref: "#/components/schemas/LisskinsItem"
        dmarket:
          type: array
          items:
            $ref: "#/components/schemas/DmarketItem"
        shadowpay:
          type: array
          items:
            $ref: "#/components/schemas/ShadowpayItem"
        waxpeer:
          type: array
          items:
            $ref: "#/components/schemas/WaxpeerItem"
        steam:
          type: array
          items:
            $ref: "#/components/schemas/SteamItem"
      required:
        - youpin
        - buff163
        - c5game
        - ecosteam
        - skinbaron
        - skinport
        - market_csgo
        - csfloat
        - lisskins
        - dmarket
        - shadowpay
        - waxpeer
        - steam
    SearchResponseNonDoppler:
      type: object
      description: Search response when the queried skin is **not** a Doppler.
      properties:
        market_hash_name:
          type: string
          example: AK-47 | Redline (Field-Tested)
        is_doppler:
          type: boolean
          enum:
            - false
        search_variants:
          type: array
          items:
            type: string
          description: Always contains exactly the input `market_hash_name`.
        data:
          $ref: "#/components/schemas/SearchDataNonDoppler"
        requestor:
          type: string
          format: email
        plan:
          type: string
        timestamp:
          $ref: "#/components/schemas/UpdatedAt"
      required:
        - market_hash_name
        - is_doppler
        - search_variants
        - data
        - timestamp
    SearchResponseDoppler:
      type: object
      description: |
        Search response when the queried skin is a Doppler or Gamma Doppler.
        The server queried all phase variants listed in `search_variants`.
      properties:
        market_hash_name:
          type: string
          example: Glock-18 | Gamma Doppler (Factory New)
        is_doppler:
          type: boolean
          enum:
            - true
        search_variants:
          type: array
          items:
            type: string
          description: |
            Every phase variant the server queried for this skin. For Gamma
            Dopplers: `(Emerald)` + `(Phase 1..4)`. For regular Dopplers:
            `(Ruby)`, `(Sapphire)`, `(Black Pearl)` + `(Phase 1..4)`.
        data:
          $ref: "#/components/schemas/SearchDataDoppler"
        requestor:
          type: string
          format: email
        plan:
          type: string
        timestamp:
          $ref: "#/components/schemas/UpdatedAt"
      required:
        - market_hash_name
        - is_doppler
        - search_variants
        - data
        - timestamp
    SearchResponse:
      description: |
        Discriminate on the top-level boolean `is_doppler` to select the
        correct variant:

        - `is_doppler: false` → `SearchResponseNonDoppler` (each marketplace key is either an item object or `null`).
        - `is_doppler: true`  → `SearchResponseDoppler`    (each marketplace key is an array of phase variants).
      oneOf:
        - $ref: "#/components/schemas/SearchResponseNonDoppler"
        - $ref: "#/components/schemas/SearchResponseDoppler"
    MarketSalesSearchResponse:
      type: object
      properties:
        market_hash_names:
          type: array
          items:
            type: string
        count:
          type: integer
        data:
          type: array
          items:
            $ref: "#/components/schemas/MarketSaleSearchItem"
        source:
          type: string
          example: Market Sales
        requestor:
          type: string
          format: email
        plan:
          type: string
        timestamp:
          $ref: "#/components/schemas/UpdatedAt"
      required:
        - market_hash_names
        - count
        - data
        - source
        - timestamp
    MarketSaleSearchItem:
      allOf:
        - $ref: "#/components/schemas/MarketSalesCsvSalesRow"
        - type: object
          properties:
            stickers:
              type: array
              items:
                $ref: "#/components/schemas/MarketSalesCsvStickersRow"
            keychains:
              type: array
              items:
                $ref: "#/components/schemas/MarketSalesCsvKeychainsRow"
          required:
            - stickers
            - keychains
    MarketSalesCsvSalesRow:
      description: One row in `sales.csv` inside the ZIP export.
      type: object
      properties:
        marketplace:
          type: string
          enum:
            - csfloat
            - youpin
            - skinport
        sale_id:
          type: string
          description: UInt64 as string.
        market_hash_name:
          type: string
        price:
          type: integer
          description: Sale price in cents.
        sold_at:
          type: string
          example: 2026-07-06 12:59:12.668
        def_index:
          type: integer
        paint_index:
          type: integer
        paint_seed:
          type: integer
        float_value:
          type: number
        is_stattrak:
          type: integer
          enum:
            - 0
            - 1
        is_souvenir:
          type: integer
          enum:
            - 0
            - 1
        rarity:
          type: integer
        quality:
          type: integer
        cs2_img:
          type: string
        fetched_at:
          type: string
          example: 2026-07-06 12:59:12.668
    MarketSalesCsvStickersRow:
      description: One row in `stickers.csv` inside the ZIP export.
      type: object
      properties:
        marketplace:
          type: string
        sale_id:
          type: string
        sold_at:
          type: string
        position_idx:
          type: integer
        sticker_id:
          type: string
        slot:
          type: integer
        sticker_name:
          type: string
        wear:
          type: number
        offset_x:
          type: number
        offset_y:
          type: number
        rotation:
          type: number
        reference_price:
          type: integer
          description: Reference price in cents.
        reference_quantity:
          type: integer
        reference_updated:
          type: string
        fetched_at:
          type: string
    MarketSalesCsvKeychainsRow:
      description: One row in `keychains.csv` inside the ZIP export.
      type: object
      properties:
        marketplace:
          type: string
        sale_id:
          type: string
        sold_at:
          type: string
        position_idx:
          type: integer
        keychain_id:
          type: string
        slot:
          type: integer
        keychain_name:
          type: string
        pattern:
          type: integer
        offset_x:
          type: number
        offset_y:
          type: number
        offset_z:
          type: number
        reference_price:
          type: integer
        reference_quantity:
          type: integer
        reference_updated:
          type: string
        fetched_at:
          type: string
    Error:
      type: object
      description: |
        Current error envelope. A future release may add an optional
        `error_details` object next to `error`; the `error` string will
        remain for backwards compatibility.
      properties:
        error:
          type: string
          description: Human-readable error message.
          example: Invalid API key
      required:
        - error
