{
  "openapi": "3.1.0",
  "info": {
    "title": "CSBoard API",
    "version": "1.0.0",
    "description": "Market data over the CSBoard marketplace — live listings, floats, stickers, minAsk prices, FX rates — plus opt-in buying straight from your balance. Free to read, key-gated, built for automation.",
    "contact": {
      "name": "CSBoard",
      "url": "https://csboard.com/docs"
    }
  },
  "servers": [
    {
      "url": "https://csboard.com/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Status",
      "description": "Liveness and freshness probes."
    },
    {
      "name": "Market data",
      "description": "Read the live catalog, prices, and FX rates."
    },
    {
      "name": "Trading",
      "description": "Buy listings from your CSBoard balance. Opt-in, key-gated."
    },
    {
      "name": "Instant Sell",
      "description": "Sell CS2, Dota 2 and Rust items from any Steam inventory to the CSBoard network and get paid to your balance. Invite-only."
    },
    {
      "name": "P2P",
      "description": "List your own CS2 skins on the CSBoard P2P market. Free — any valid key, no balance requirement."
    },
    {
      "name": "Account",
      "description": "Your balance, settled funds, and trading status."
    },
    {
      "name": "Webhooks",
      "description": "Register an endpoint and receive signed order updates instead of polling."
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "tags": [
          "Status"
        ],
        "summary": "Liveness + freshness probe",
        "description": "Liveness and price-list freshness probe. No key required — use it to check the API is up and the price list is fresh. One of two endpoints that work without authentication; the other is `GET /public/prices`.",
        "operationId": "getHealth",
        "security": [],
        "responses": {
          "200": {
            "description": "Service is up.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                },
                "example": {
                  "status": "ok",
                  "groups": 184213,
                  "price_list_age_seconds": 42
                }
              }
            }
          }
        }
      }
    },
    "/listings": {
      "get": {
        "tags": [
          "Market data"
        ],
        "summary": "Live buyable listings",
        "description": "Live buyable listings across the marketplace — each with float, paint seed, stickers, and the asking price in USD. Use keyset pagination via `cursor`. Pass `appId` to read Dota 2 (`570`) or Rust (`252490`) instead of CS2 — rows have the same keys, with the CS2-only fields `null` and `stickers` empty.",
        "operationId": "listListings",
        "parameters": [
          {
            "$ref": "#/components/parameters/AppId"
          },
          {
            "name": "search",
            "in": "query",
            "description": "Full-text match on market hash name.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "query",
            "required": false,
            "description": "Exact market_hash_name (case-insensitive) — the precise single-item lookup. Unlike fuzzy `search`, it isolates one item even when its name is a word-subset of a longer one (e.g. `Spectrum Case` vs `Spectrum 2 Case`). Takes precedence over `search`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "description": "e.g. Rifle, Knife, Gloves.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "wear",
            "in": "query",
            "description": "Item wear bucket. CS2 only — sent with another `appId` it answers `400 invalid_param`.",
            "schema": {
              "type": "string",
              "enum": [
                "Factory New",
                "Minimal Wear",
                "Field-Tested",
                "Well-Worn",
                "Battle-Scarred"
              ]
            }
          },
          {
            "name": "rarity",
            "in": "query",
            "description": "e.g. Classified, Covert.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "min_price",
            "in": "query",
            "description": "Minimum price in USD.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "max_price",
            "in": "query",
            "description": "Maximum price in USD.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "min_float",
            "in": "query",
            "description": "Minimum float value. CS2 only — sent with another `appId` it answers `400 invalid_param`.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "max_float",
            "in": "query",
            "description": "Maximum float value. CS2 only — sent with another `appId` it answers `400 invalid_param`.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "delivery",
            "in": "query",
            "description": "Delivery bucket, the same three the site's grid shows. `instant` = bot fulfilment (seconds to minutes); `up_to_12h` = a human seller on the source market must send the trade; `hold` = inside a Steam trade lock until the item's tradable_at. Any other value is a 400.",
            "schema": {
              "type": "string",
              "enum": [
                "instant",
                "up_to_12h",
                "hold"
              ]
            }
          },
          {
            "name": "min_refund_percent",
            "in": "query",
            "description": "Only listings whose refund_percent is at least this (0-100). Listings with no published figure are EXCLUDED, not assumed. Combine with delivery=instant for a pool that ships now and is fully refundable on a Steam reversal.",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "stat_trak",
            "in": "query",
            "description": "Filter StatTrak™ items. CS2 only — sent with another `appId` it answers `400 invalid_param`.",
            "schema": {
              "type": "string",
              "enum": [
                "only",
                "exclude"
              ]
            }
          },
          {
            "name": "souvenir",
            "in": "query",
            "description": "Filter Souvenir items. CS2 only — sent with another `appId` it answers `400 invalid_param`.",
            "schema": {
              "type": "string",
              "enum": [
                "only",
                "exclude"
              ]
            }
          },
          {
            "name": "available_after",
            "in": "query",
            "required": false,
            "description": "ISO-8601 timestamp. Returns only listings that entered the catalogue after it — the delta-poll parameter. Pair with `sort=newest`; the usual response is an empty page, which is what makes frequent polling cheap instead of a full rescan every tick.\n\n**Overlap your watermark by ~60 seconds and dedupe by `id`.** Send `max(listed_at) - 60s`, never the bare maximum. Timestamps come from the start of the database transaction that published the listing, so a large batch can commit rows stamped *earlier* than rows a smaller, later batch already committed; a watermark advanced to the exact maximum steps over those listings permanently. CS2 only — sent with another `appId` it answers `400 invalid_param`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-07-27T09:13:02.481Z"
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sort order. Default id. `newest` orders by `listed_at` (when the item entered the catalogue), so re-listings surface too. `newest` is CS2 only — with another `appId` it answers `400 invalid_param`.",
            "schema": {
              "type": "string",
              "enum": [
                "id",
                "newest",
                "price_asc",
                "price_desc"
              ],
              "default": "id"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Keyset cursor from next_cursor.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of listings.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Listing"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass back as `cursor` to fetch the next page. Null on the last page."
                    }
                  },
                  "required": [
                    "items",
                    "next_cursor"
                  ]
                },
                "example": {
                  "items": [
                    {
                      "id": "itm_8841201",
                      "market_hash_name": "AK-47 | Redline (Minimal Wear)",
                      "wear": "Minimal Wear",
                      "doppler_phase": null,
                      "float_value": 0.0912,
                      "paint_seed": 412,
                      "stickers": [
                        {
                          "name": "Crown (Foil)",
                          "image": "https://cdn.csboard.com/stickers/crown_foil.png",
                          "slot": 0,
                          "wear": 0.0
                        }
                      ],
                      "price_usd": 14.37,
                      "category": "Rifle",
                      "rarity": "Classified",
                      "image": "https://cdn.csboard.com/items/ak47_redline_mw.png",
                      "inspect_link": "steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20...",
                      "tradable": false,
                      "tradable_at": "2026-07-06T12:00:00Z",
                      "delivery": "hold",
                      "refund_percent": 100,
                      "listed_at": "2026-06-29T08:41:17.000Z"
                    }
                  ],
                  "next_cursor": "eyJpZCI6Iml0bV84ODQxMjAxIn0="
                }
              }
            }
          },
          "400": {
            "description": "A malformed or CS2-only parameter (`invalid_param`), or an `appId` this key may not use (`unsupported_game`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_param": {
                    "summary": "CS2-only filter sent with another game",
                    "value": {
                      "code": "invalid_param",
                      "detail": "wear is CS2-only and is not supported for appId 570 (Dota 2)."
                    }
                  },
                  "unsupported_game": {
                    "summary": "Game not available to this key",
                    "value": {
                      "code": "unsupported_game",
                      "detail": "appId 440 is not available to this key. Supported: 730 (CS2), 570 (Dota 2), 252490 (Rust).",
                      "supported_app_ids": [
                        730,
                        570,
                        252490
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/listings/stream": {
      "get": {
        "tags": [
          "Market data"
        ],
        "summary": "Stream listings as they appear and disappear",
        "description": "Server-Sent Events feed of the catalogue changing. One connection replaces any polling loop.\n\nPolling cannot answer \"what is new?\" cheaply — every client that tries ends up re-reading the same first page on a timer. It also cannot answer \"what is gone?\" at all: a poller only learns an item sold by trying to buy it and failing. This endpoint pushes both edges.\n\n### Events\n\n- `new` — data is exactly the `Listing` object `/v1/listings` returns.\n- `gone` — data is `{ \"id\": \"…\" }`. The item left the catalogue. **Act on this.** Dropping items as they sell is the difference between your buy calls succeeding and your buy calls discovering the item was already gone.\n- `resync` — your `Last-Event-ID` predates the retained history, so a replay would be incomplete. Re-read `/v1/listings?sort=newest` before trusting the stream again.\n\n### Reconnecting without gaps\n\nEvery event carries an id. Send the last one you processed back as the `Last-Event-ID` header and you receive exactly what you missed — including across our deploys. A `: heartbeat` comment arrives every 25 seconds; treat a longer silence as a dead connection and reconnect.\n\n### Limits\n\nThree concurrent streams per key. One stream already carries the whole catalogue, so the filters below are for your bandwidth, not for working around that.\n\n```\n: connected\n\nid: 1785312840123-0\nevent: new\ndata: {\"id\":\"000012e8-…\",\"market_hash_name\":\"AK-47 | Redline (Field-Tested)\",\"price_usd\":31.2,\"delivery\":\"instant\",\"listed_at\":\"2026-07-27T09:14:02.481Z\"}\n\nid: 1785312851904-0\nevent: gone\ndata: {\"id\":\"000012e8-…\"}\n\n: heartbeat\n``` CS2 only — this endpoint does not read `appId`.",
        "operationId": "streamListings",
        "parameters": [
          {
            "name": "min_price",
            "in": "query",
            "required": false,
            "description": "Only stream listings at or above this USD price.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "max_price",
            "in": "query",
            "required": false,
            "description": "Only stream listings at or below this USD price.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "e.g. Rifle, Knife, Gloves.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rarity",
            "in": "query",
            "required": false,
            "description": "e.g. Classified, Covert.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "wear",
            "in": "query",
            "required": false,
            "description": "Exact wear name.",
            "schema": {
              "type": "string",
              "enum": [
                "Factory New",
                "Minimal Wear",
                "Field-Tested",
                "Well-Worn",
                "Battle-Scarred"
              ]
            }
          },
          {
            "name": "name",
            "in": "query",
            "required": false,
            "description": "Exact market_hash_name (case-insensitive).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "stat_trak",
            "in": "query",
            "required": false,
            "description": "Filter StatTrak™ items.",
            "schema": {
              "type": "string",
              "enum": [
                "only",
                "exclude"
              ]
            }
          },
          {
            "name": "souvenir",
            "in": "query",
            "required": false,
            "description": "Filter Souvenir items.",
            "schema": {
              "type": "string",
              "enum": [
                "only",
                "exclude"
              ]
            }
          },
          {
            "name": "delivery",
            "in": "query",
            "description": "Narrow `new` events to one delivery bucket (`instant` or `hold`). `gone` events are never filtered — a missed removal is the ghost listing this feed exists to prevent.",
            "schema": {
              "type": "string",
              "enum": [
                "instant",
                "up_to_12h",
                "hold"
              ]
            }
          },
          {
            "name": "last_event_id",
            "in": "query",
            "required": false,
            "description": "Resume after this event id. Use only if your client cannot send the `Last-Event-ID` header.",
            "schema": {
              "type": "string"
            },
            "example": "1785312840123-0"
          },
          {
            "name": "min_refund_percent",
            "in": "query",
            "description": "Narrow `new` events to listings whose refund_percent is at least this (0-100). `gone` events are never filtered.",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "An open SSE stream. Stays open until you disconnect.",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many concurrent streams for this key (max 3).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/games": {
      "get": {
        "tags": [
          "Market data"
        ],
        "summary": "Games you can pass as appId",
        "description": "The games this key may read with `appId`, CS2 first, and whether it may also buy there (`tradable`). Key only — no balance requirement, so you can check it before funding.",
        "operationId": "listGames",
        "responses": {
          "200": {
            "description": "Games available to this key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "games": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Game"
                      }
                    }
                  },
                  "required": [
                    "games"
                  ]
                },
                "example": {
                  "games": [
                    {
                      "appId": 730,
                      "name": "CS2",
                      "tradable": true
                    },
                    {
                      "appId": 570,
                      "name": "Dota 2",
                      "tradable": true
                    },
                    {
                      "appId": 252490,
                      "name": "Rust",
                      "tradable": true
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/prices": {
      "get": {
        "tags": [
          "Market data"
        ],
        "summary": "minAsk price list",
        "description": "The minAsk price list — one row per market hash name (+ wear + Doppler phase), with the cheapest current ask and how many are listed. Indicative grouped snapshot; can lag the live listing price. Pass `appId` to read Dota 2 (`570`) or Rust (`252490`) instead of CS2 — rows have the same keys, with the CS2-only fields `null` and `stickers` empty.",
        "operationId": "listPrices",
        "parameters": [
          {
            "$ref": "#/components/parameters/AppId"
          },
          {
            "name": "search",
            "in": "query",
            "description": "Full-text match on market hash name.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "query",
            "required": false,
            "description": "Exact market_hash_name (case-insensitive) — the precise single-item lookup. Unlike fuzzy `search`, it isolates one item even when its name is a word-subset of a longer one (e.g. `Spectrum Case` vs `Spectrum 2 Case`). Takes precedence over `search`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "description": "e.g. Rifle, Knife, Gloves.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "wear",
            "in": "query",
            "description": "Item wear bucket. CS2 only — sent with another `appId` it answers `400 invalid_param`.",
            "schema": {
              "type": "string",
              "enum": [
                "Factory New",
                "Minimal Wear",
                "Field-Tested",
                "Well-Worn",
                "Battle-Scarred"
              ]
            }
          },
          {
            "name": "rarity",
            "in": "query",
            "description": "e.g. Classified, Covert.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "min_price",
            "in": "query",
            "description": "Minimum price in USD.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "max_price",
            "in": "query",
            "description": "Maximum price in USD.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Keyset cursor from next_cursor.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "1–500. Default 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of price rows.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PriceRow"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "items",
                    "next_cursor"
                  ]
                },
                "example": {
                  "items": [
                    {
                      "market_hash_name": "AK-47 | Redline (Field-Tested)",
                      "wear": "Field-Tested",
                      "doppler_phase": null,
                      "min_price_usd": 11.92,
                      "qty": 73
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "A malformed or CS2-only parameter (`invalid_param`), or an `appId` this key may not use (`unsupported_game`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_param": {
                    "summary": "CS2-only filter sent with another game",
                    "value": {
                      "code": "invalid_param",
                      "detail": "wear is CS2-only and is not supported for appId 252490 (Rust)."
                    }
                  },
                  "unsupported_game": {
                    "summary": "Game not available to this key",
                    "value": {
                      "code": "unsupported_game",
                      "detail": "appId 440 is not available to this key. Supported: 730 (CS2), 570 (Dota 2), 252490 (Rust).",
                      "supported_app_ids": [
                        730,
                        570,
                        252490
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/prices/snapshot.ndjson.gz": {
      "get": {
        "tags": [
          "Market data"
        ],
        "summary": "Full price-list snapshot (gzipped NDJSON)",
        "description": "Full gzipped NDJSON dump of the price list — one price row JSON per line. Use this for full-catalog ingestion (e.g. comparison sites), not pagination. Rate limited to 1 request/minute. Supports ETag / If-None-Match: an unchanged snapshot returns 304 Not Modified. CS2 only — this endpoint does not read `appId`.",
        "operationId": "getPriceSnapshot",
        "parameters": [
          {
            "name": "If-None-Match",
            "in": "header",
            "description": "Conditional request. Pass the ETag from a previous snapshot to receive 304 if unchanged.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Gzipped NDJSON stream. Each decompressed line is one PriceRow JSON object. Sets an ETag header.",
            "headers": {
              "ETag": {
                "description": "Opaque snapshot version. Send back as If-None-Match to skip unchanged downloads.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/x-ndjson": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "304": {
            "description": "Not Modified — the snapshot has not changed since the ETag you sent."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/public/prices": {
      "get": {
        "tags": [
          "Market data"
        ],
        "summary": "Keyless min-ask feed",
        "description": "One number per item: the cheapest current ask in USD for every `market_hash_name` on sale in one game. **No API key and no balance requirement** — send no `Authorization` header. In exchange it is limited to 1 request per minute per IP address, and the payload is rebuilt at most once a minute (`Cache-Control: public, max-age=60`), so polling faster gains nothing.\n\nCS2 Doppler and Gamma Doppler phases are merged into Steam's own base name, so every key matches a real Steam `market_hash_name`. For depth, counts, wear, filters or paging use the keyed `GET /prices`.",
        "operationId": "getPublicPrices",
        "security": [],
        "parameters": [
          {
            "name": "appId",
            "in": "query",
            "required": false,
            "description": "Game to price: `730` = CS2 (the default), `570` = Dota 2, `252490` = Rust. A game that is not available answers `400 invalid_param`.",
            "schema": {
              "type": "integer",
              "enum": [
                730,
                570,
                252490
              ],
              "default": 730
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Name → min-ask map for the game.",
            "headers": {
              "Cache-Control": {
                "description": "`public, max-age=60`.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicPrices"
                },
                "example": {
                  "appId": 730,
                  "currency": "USD",
                  "updatedAt": "2026-10-02T12:00:41.512Z",
                  "items": {
                    "AK-47 | Redline (Field-Tested)": 11.92,
                    "AWP | Asiimov (Field-Tested)": 96.4,
                    "Karambit | Doppler (Factory New)": 812.5
                  }
                }
              }
            }
          },
          "400": {
            "description": "The `appId` is not available.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "invalid_param",
                  "detail": "appId \"440\" is not available. Use one of: 730, 570, 252490."
                }
              }
            }
          },
          "429": {
            "description": "More than 1 request in a minute from your IP address. Wait `Retry-After` seconds. This limit is enforced per address, not per key, and its body has no `code` field — branch on the status code.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "statusCode": {
                      "type": "integer"
                    }
                  }
                },
                "example": {
                  "error": "Rate limit exceeded, retry in 37 seconds",
                  "statusCode": 429
                }
              }
            }
          }
        }
      }
    },
    "/currency": {
      "get": {
        "tags": [
          "Market data"
        ],
        "summary": "FX rates (USD base)",
        "description": "FX rates with USD as the base. Every price in this API is USD — use this to convert to a local currency. Same rate table the site and payment flows use (cached ~1h).",
        "operationId": "getCurrency",
        "responses": {
          "200": {
            "description": "Current FX rates.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Currency"
                },
                "example": {
                  "base": "USD",
                  "rates": {
                    "USD": 1,
                    "EUR": 0.92,
                    "RUB": 78.4,
                    "GBP": 0.79
                  },
                  "updated_at": "2026-06-29T17:00:00Z",
                  "rub_source": "cbr",
                  "base_source": "openexchangerates"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/orders": {
      "get": {
        "tags": [
          "Trading"
        ],
        "summary": "List purchase history",
        "description": "Your purchase history, newest first, with keyset pagination. Filter by time window and status. Pass `meta.next_cursor` back as `cursor` to walk older pages; `next_cursor` is null on the last page.",
        "operationId": "listOrders",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page. 1–100. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "start_unix_time",
            "in": "query",
            "description": "Only orders created at or after this Unix timestamp (seconds).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "end_unix_time",
            "in": "query",
            "description": "Only orders created at or before this Unix timestamp (seconds).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by order status.",
            "schema": {
              "type": "string",
              "enum": [
                "completed",
                "hold",
                "delivering",
                "pending",
                "cancelled",
                "failed"
              ]
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Keyset cursor from a previous response's `meta.next_cursor`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of orders.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Order"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "next_cursor": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Pass back as `cursor` for the next page. Null on the last page."
                        },
                        "per_page": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "next_cursor",
                        "per_page"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                },
                "example": {
                  "data": [
                    {
                      "order_id": "ord_01J9Z3K8Q2",
                      "steam_id": "76561198000000000",
                      "status": "completed",
                      "custom_id": "batch-2026-06-29-01",
                      "currency": "USD",
                      "charged_total_usd": 26.47,
                      "item_count": 2,
                      "hold_until": null,
                      "created_at": "2026-06-29T17:12:04Z",
                      "updated_at": "2026-06-29T17:15:40Z",
                      "items": [
                        {
                          "market_hash_name": "AK-47 | Redline (Minimal Wear)",
                          "price_usd": 14.37,
                          "status": "delivered",
                          "tradable_at": "2026-07-06T12:00:00Z",
                          "return_reason": null,
                          "steam_trade_offer_id": "5512345678",
                          "steam_trade_offer_finished_at": "2026-06-29T17:15:40Z"
                        }
                      ]
                    }
                  ],
                  "meta": {
                    "next_cursor": "eyJpZCI6Im9yZF8wMUo5WjNLOFEyIn0=",
                    "per_page": 50
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "description": "Invalid request parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "invalid_request",
                  "detail": "limit must be between 1 and 100."
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "tags": [
          "Trading"
        ],
        "summary": "Buy listings from your balance",
        "description": "Buy 1–10 listings by id, debited from your CSBoard balance. Requires trading enabled on the key + a linked Steam account and trade URL. Buys are charged at the LIVE price at execution; always send `max_price_usd` as an atomic overcharge ceiling. Answers `201` with the new order. Idempotent via the `Idempotency-Key` header or `idempotency_key` in the body — a replay answers `200` with the original body. To buy Dota 2 or Rust listings, send `appId` in the body with the ids you read under that `appId`; such orders answer `delivery: \"pending\"` and `expected_minutes: null`.",
        "operationId": "createOrder",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional, 8–128 characters. A retried request with the same key replays the original order (`200` with `Idempotent-Replayed: true`) instead of buying twice; while the first request is still running it answers `409 idempotency_in_progress`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderRequest"
              },
              "example": {
                "item_ids": [
                  "itm_8841201",
                  "itm_8841340"
                ],
                "max_price_usd": 30.0,
                "idempotency_key": "6f9c2b10-1a2b-4c3d-8e4f-5a6b7c8d9e0f"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Order created and debited from your balance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderCreated"
                },
                "example": {
                  "order_id": "cmg9x2k1p0007qz3h5v8w2r4n",
                  "status": "paid",
                  "currency": "USD",
                  "charged_total_usd": 26.47,
                  "item_count": 2,
                  "items": [
                    {
                      "market_hash_name": "AK-47 | Redline (Minimal Wear)",
                      "price_usd": 14.37,
                      "status": null
                    },
                    {
                      "market_hash_name": "AWP | Atheris (Field-Tested)",
                      "price_usd": 12.1,
                      "status": null
                    }
                  ],
                  "delivery": "instant",
                  "expected_minutes": 1,
                  "created_at": "2026-06-29T17:12:04.000Z",
                  "updated_at": "2026-06-29T17:12:04.000Z"
                }
              }
            }
          },
          "200": {
            "description": "Idempotent replay: a request with an `Idempotency-Key` (or `idempotency_key`) already used for a completed order returns that original response body, with the header `Idempotent-Replayed: true`. Nothing new is bought.",
            "headers": {
              "Idempotent-Replayed": {
                "description": "`true` on a replayed response.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderCreated"
                },
                "example": {
                  "order_id": "cmg9x2k1p0007qz3h5v8w2r4n",
                  "status": "paid",
                  "currency": "USD",
                  "charged_total_usd": 26.47,
                  "item_count": 2,
                  "items": [
                    {
                      "market_hash_name": "AK-47 | Redline (Minimal Wear)",
                      "price_usd": 14.37,
                      "status": null
                    },
                    {
                      "market_hash_name": "AWP | Atheris (Field-Tested)",
                      "price_usd": 12.1,
                      "status": null
                    }
                  ],
                  "delivery": "instant",
                  "expected_minutes": 1,
                  "created_at": "2026-06-29T17:12:04.000Z",
                  "updated_at": "2026-06-29T17:12:04.000Z"
                }
              }
            }
          },
          "400": {
            "description": "Bad request — a malformed body (`invalid_request`, whose `detail` is the field-error map), an id that cannot be bought here, items that must be split into separate orders, no linked Steam account, or an `appId` this key may not buy in (`unsupported_game`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Malformed body",
                    "value": {
                      "code": "invalid_request",
                      "detail": {
                        "formErrors": [],
                        "fieldErrors": {
                          "item_ids": [
                            "Duplicate item ids are not allowed"
                          ]
                        }
                      }
                    }
                  },
                  "unsupported_game": {
                    "summary": "Game this key may not buy in",
                    "value": {
                      "code": "unsupported_game",
                      "detail": "appId 440 is not available to this key. Supported: 730 (CS2), 570 (Dota 2), 252490 (Rust).",
                      "supported_app_ids": [
                        730,
                        570,
                        252490
                      ]
                    }
                  },
                  "unsupported_item": {
                    "summary": "Id not buyable through the API",
                    "value": {
                      "code": "unsupported_item",
                      "detail": "Live (ss_live_*) ids are not buyable via API. Use ids from /v1/listings."
                    }
                  },
                  "steam_account_required": {
                    "summary": "No linked Steam account or trade URL",
                    "value": {
                      "code": "steam_account_required",
                      "detail": "Link your Steam account and trade URL on csboard.com before buying via API."
                    }
                  },
                  "cannot_mix_sources": {
                    "summary": "Items that cannot share one order",
                    "value": {
                      "code": "cannot_mix_sources",
                      "detail": "Buy external-market and platform items in separate orders."
                    }
                  },
                  "one_external_per_order": {
                    "summary": "Only one such item per order",
                    "value": {
                      "code": "one_external_per_order",
                      "detail": "Only one external-market item per order."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict — the live price moved past your ceiling, an item sold out, a duplicate Idempotency-Key is still processing, the recipient has too many pending offers, prices are mid-refresh, or a concurrent order won the race. Nothing was charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "price_moved": {
                    "summary": "Live price exceeded max_price_usd",
                    "value": {
                      "code": "price_moved",
                      "detail": "Live price exceeds your max_price_usd. Re-read /v1/listings and retry.",
                      "quoted_max_usd": 30.0,
                      "current_total_usd": 31.2,
                      "items": [
                        {
                          "id": "itm_8841201",
                          "market_hash_name": "AK-47 | Redline (Minimal Wear)",
                          "price_usd": 15.1
                        },
                        {
                          "id": "itm_8841340",
                          "market_hash_name": "AWP | Atheris (Field-Tested)",
                          "price_usd": 16.1
                        }
                      ]
                    }
                  },
                  "item_unavailable": {
                    "summary": "Item sold out",
                    "value": {
                      "code": "item_unavailable",
                      "detail": "One or more items are no longer available.",
                      "unavailable_ids": [
                        "itm_8841999"
                      ]
                    }
                  },
                  "idempotency_in_progress": {
                    "summary": "Earlier request still running",
                    "value": {
                      "code": "idempotency_in_progress",
                      "detail": "A request with this Idempotency-Key is still processing."
                    }
                  },
                  "concurrent_update": {
                    "summary": "Lost a concurrent-update race",
                    "value": {
                      "code": "concurrent_update",
                      "detail": "Another order touched the same items at the same moment and this one was rolled back. Nothing was charged — retry."
                    }
                  },
                  "pending_trades_limit": {
                    "summary": "Recipient has too many unaccepted offers",
                    "value": {
                      "code": "pending_trades_limit",
                      "detail": "The recipient has too many pending Steam trade offers; they must accept them before more can be delivered.",
                      "limit": 5
                    }
                  },
                  "price_updating": {
                    "summary": "Prices mid-refresh",
                    "value": {
                      "code": "price_updating",
                      "detail": "Prices are being updated — retry in a moment."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "Payment required — the balance does not cover the order, or the purchase needs identity verification first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_balance": {
                    "summary": "Balance too low",
                    "value": {
                      "code": "insufficient_balance",
                      "detail": "Top up your CSBoard balance to cover this order.",
                      "required_usd": 26.47,
                      "current_usd": 10.0
                    }
                  },
                  "kyc_required": {
                    "summary": "Identity verification needed",
                    "value": {
                      "code": "kyc_required",
                      "detail": "Identity verification required before this purchase.",
                      "kyc_url": "https://csboard.com/...",
                      "reasons": [
                        "..."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — trading is not enabled on this key, the account is restricted, or the account is not eligible for this purchase.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "trading_not_enabled": {
                    "summary": "Buying disabled for this key",
                    "value": {
                      "code": "trading_not_enabled",
                      "detail": "Buying via API is disabled for this key. Enable it at https://csboard.com/profile?tab=api"
                    }
                  },
                  "account_restricted": {
                    "summary": "Account restricted",
                    "value": {
                      "code": "account_restricted",
                      "detail": "Account is restricted — contact support."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "description": "Unexpected failure. The order may still exist — check `GET /orders/info` with your `custom_id` before retrying.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "order_failed",
                  "detail": "Could not complete the order."
                }
              }
            }
          },
          "503": {
            "description": "The marketplace for one of the items is temporarily unavailable. No charge was made.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "market_unavailable",
                  "detail": "The marketplace for one of these items is temporarily unavailable — retry shortly. No charge was made."
                }
              }
            }
          },
          "504": {
            "description": "Upstream marketplace did not answer in time. The outcome of the purchase is UNKNOWN — it may still have completed. Do NOT re-send blindly: poll the order list, or re-send the identical custom_id / Idempotency-Key, which replays the original result instead of buying again. A retry sent while the original is still unresolved returns 409 idempotency_in_progress.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "upstream_timeout",
                  "detail": "The marketplace did not answer in time, so the outcome of this purchase is UNKNOWN — it may still have gone through. Do not re-send blindly: poll the order list (or re-send the identical custom_id, which replays rather than buys) before treating it as failed."
                }
              }
            }
          }
        }
      }
    },
    "/balance": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Account balance and trading status",
        "description": "Your current balance in USD, plus how much of it is settled (reversal-safe) versus held. Use `settled_balance_usd` to know what is available for reversal-safe spending, and `trading_enabled` to check whether buying is turned on for this key.",
        "operationId": "getBalance",
        "responses": {
          "200": {
            "description": "Current balance and trading status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                },
                "example": {
                  "currency": "USD",
                  "balance_usd": 1240.55,
                  "trading_enabled": true,
                  "settled_balance_usd": 980.1,
                  "held_usd": 260.45,
                  "held_until": "2026-07-06T12:00:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/listings/availability": {
      "get": {
        "tags": [
          "Market data"
        ],
        "summary": "Bulk availability check",
        "description": "Check whether specific listings are still buyable, in one request. Pass up to 100 listing ids as a comma-separated `ids` query parameter. Returns the live price of every id that is still available, plus the ids that are no longer available. For Dota 2 or Rust listings pass the same `appId` you read them with.",
        "operationId": "getListingsAvailability",
        "parameters": [
          {
            "name": "ids",
            "in": "query",
            "required": true,
            "description": "Comma-separated listing ids. Required. Maximum 100 ids per request.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/AppId"
          }
        ],
        "responses": {
          "200": {
            "description": "Availability map for the requested ids.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "available": {
                          "type": "object",
                          "additionalProperties": {
                            "type": "number"
                          },
                          "description": "Map of listing id → its current price in USD, for every id that is still available."
                        },
                        "unavailable_ids": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Ids that are no longer available."
                        }
                      },
                      "required": [
                        "available",
                        "unavailable_ids"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "data": {
                    "available": {
                      "itm_8841201": 14.37,
                      "itm_8841340": 12.1
                    },
                    "unavailable_ids": [
                      "itm_8841999"
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "An `appId` this key may not use (`unsupported_game`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unsupported_game": {
                    "summary": "Game not available to this key",
                    "value": {
                      "code": "unsupported_game",
                      "detail": "appId 440 is not available to this key. Supported: 730 (CS2), 570 (Dota 2), 252490 (Rust).",
                      "supported_app_ids": [
                        730,
                        570,
                        252490
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "description": "Invalid request — `ids` missing or more than 100 ids supplied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "invalid_request",
                  "detail": "Provide between 1 and 100 ids in the ids parameter."
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/orders/info": {
      "get": {
        "tags": [
          "Trading"
        ],
        "summary": "Batch order lookup",
        "description": "Look up the status of many orders at once by `custom_ids` and/or `order_ids` (comma-separated). Supply at least one of the two; up to 200 ids in total across both parameters.",
        "operationId": "getOrdersInfo",
        "parameters": [
          {
            "name": "custom_ids",
            "in": "query",
            "description": "Comma-separated custom ids you assigned at purchase time.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "order_ids",
            "in": "query",
            "description": "Comma-separated CSBoard order ids.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching orders.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Order"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "data": [
                    {
                      "order_id": "ord_01J9Z3K8Q2",
                      "steam_id": "76561198000000000",
                      "status": "completed",
                      "custom_id": "batch-2026-06-29-01",
                      "currency": "USD",
                      "charged_total_usd": 26.47,
                      "item_count": 2,
                      "hold_until": null,
                      "created_at": "2026-06-29T17:12:04Z",
                      "updated_at": "2026-06-29T17:15:40Z",
                      "items": []
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "description": "Invalid request — no ids supplied, or more than 200 ids in total.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "invalid_request",
                  "detail": "Provide custom_ids and/or order_ids, up to 200 ids total."
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/orders/{id}": {
      "get": {
        "tags": [
          "Trading"
        ],
        "summary": "Get a single order",
        "description": "Fetch one order by its CSBoard order id, including per-item delivery status.",
        "operationId": "getOrder",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "CSBoard order id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The order.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                },
                "example": {
                  "order_id": "ord_01J9Z3K8Q2",
                  "steam_id": "76561198000000000",
                  "status": "completed",
                  "custom_id": "batch-2026-06-29-01",
                  "currency": "USD",
                  "charged_total_usd": 26.47,
                  "item_count": 2,
                  "hold_until": null,
                  "created_at": "2026-06-29T17:12:04Z",
                  "updated_at": "2026-06-29T17:15:40Z",
                  "items": [
                    {
                      "market_hash_name": "AK-47 | Redline (Minimal Wear)",
                      "price_usd": 14.37,
                      "status": "delivered",
                      "tradable_at": "2026-07-06T12:00:00Z",
                      "return_reason": null,
                      "steam_trade_offer_id": "5512345678",
                      "steam_trade_offer_finished_at": "2026-06-29T17:15:40Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "No order with that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "order_not_found",
                  "detail": "No order found for that id."
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/orders/{id}/claim": {
      "post": {
        "tags": [
          "Trading"
        ],
        "summary": "Claim a held order",
        "description": "Release delivery of a held (escrow) order once its hold has cleared. Held orders appear with `status: \"hold\"` and a `hold_until` timestamp; after `hold_until` passes some orders deliver automatically while others require this explicit claim. On a successful claim the marketplace sends a Steam trade offer to your trade URL that your bot must accept within ~15 minutes or it is cancelled and refunded. Idempotent: a duplicate call while one is in flight returns a conflict, never a double-send. Prefer the account-wide `autoclaim` setting if you would rather never call this per order.",
        "operationId": "claimOrder",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "CSBoard order id of the held order to claim.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Claim accepted. `claimed: true` means the trade was released now; `claimed: false` means this order delivers automatically and no action was needed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "order_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "delivering",
                        "hold"
                      ]
                    },
                    "claimed": {
                      "type": "boolean"
                    },
                    "steam_trade_offer_id": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Present when claimed just released a trade offer."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Present on the auto-delivering no-op case."
                    }
                  },
                  "required": [
                    "order_id",
                    "status",
                    "claimed"
                  ]
                },
                "examples": {
                  "released": {
                    "summary": "Manual hold released",
                    "value": {
                      "order_id": "ord_01J9Z3K8Q2",
                      "status": "delivering",
                      "claimed": true,
                      "steam_trade_offer_id": "5512345678"
                    }
                  },
                  "auto": {
                    "summary": "Auto-delivering hold (no-op)",
                    "value": {
                      "order_id": "ord_01J9Z3K8Q2",
                      "status": "hold",
                      "claimed": false,
                      "detail": "This order delivers automatically once its hold clears; no claim needed."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "No order with that id on this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "order_not_found",
                  "detail": "No such order on this account."
                }
              }
            }
          },
          "409": {
            "description": "The order is not in a claimable (held) state, or cannot be claimed right now.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "not_claimable",
                  "detail": "Order status is 'completed'; only held orders can be claimed."
                }
              }
            }
          },
          "425": {
            "description": "The item is still under its hold window. Retry after `hold_until`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "hold_until": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "code": "hold_not_cleared",
                  "hold_until": "2026-07-02T20:00:00Z",
                  "detail": "Item is still under its hold window; retry after hold_until."
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "description": "Withdraw was attempted but the marketplace rejected it. If the hold was cancelled upstream your balance was refunded (`refunded: true`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "detail": {
                      "type": "string"
                    },
                    "refunded": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "code": "delivery_failed",
                  "detail": "The hold was cancelled upstream; your balance was refunded.",
                  "refunded": true
                }
              }
            }
          }
        }
      }
    },
    "/market/buy": {
      "post": {
        "tags": [
          "Trading"
        ],
        "summary": "Buy and deliver to a Steam trade URL",
        "description": "Buy up to 100 items and deliver them straight to any Steam trade URL you supply (built from `partner` + `token`), paid from your **settled** (reversal-safe) balance. Built for wholesale and automated delivery. Idempotent via the `custom_id` body field — a retry with the same `custom_id` replays the original purchase and the response carries the `Idempotent-Replayed: true` header. This endpoint ships behind a kill-switch and requires a trading-enabled, reversal-clean account. CS2 only — this endpoint does not read `appId`.",
        "operationId": "marketBuy",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExternalBuyRequest"
              },
              "example": {
                "item_ids": [
                  "itm_8841201",
                  "itm_8841340"
                ],
                "partner": "447383001",
                "token": "Ab3xZ9Qp",
                "max_price_usd": 30.0,
                "custom_id": "batch-2026-06-29-01",
                "skip_unavailable": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Purchase accepted and debited from settled balance.",
            "headers": {
              "Idempotent-Replayed": {
                "description": "Present and `true` when this response replays an earlier purchase made with the same `custom_id`.",
                "schema": {
                  "type": "boolean"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExternalBuyResult"
                },
                "example": {
                  "data": {
                    "purchase_id": "pur_01J9Z3K8Q2",
                    "steam_id": "76561198000000000",
                    "created_at": "2026-06-29T17:12:04Z",
                    "custom_id": "batch-2026-06-29-01",
                    "skins": [
                      {
                        "name": "AK-47 | Redline (Minimal Wear)",
                        "price": 14.37,
                        "status": "delivering",
                        "return_reason": null,
                        "steam_trade_offer_id": "5512345678"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Malformed body",
                    "value": {
                      "code": "invalid_request",
                      "detail": "item_ids must contain 1–100 unique ids."
                    }
                  },
                  "unsupported_item": {
                    "summary": "Item cannot be delivered this way",
                    "value": {
                      "code": "unsupported_item",
                      "detail": "One or more items cannot be delivered via this endpoint."
                    }
                  },
                  "invalid_trade_url": {
                    "summary": "Bad partner/token",
                    "value": {
                      "code": "invalid_trade_url",
                      "detail": "partner and token do not form a valid Steam trade URL."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "invalid_api_key",
                  "detail": "Missing or invalid API key."
                }
              }
            }
          },
          "402": {
            "description": "Not enough funds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_settled_balance": {
                    "summary": "Funds are inside the reversal window",
                    "value": {
                      "code": "insufficient_settled_balance",
                      "detail": "External delivery is payable only from settled (reversal-safe) balance. Wait for in-window credit to settle or top up.",
                      "required_usd": 26.47,
                      "balance_usd": 30.0,
                      "settled_usd": 10.0
                    }
                  },
                  "insufficient_balance": {
                    "summary": "Balance too low — top up",
                    "value": {
                      "code": "insufficient_balance",
                      "detail": "Balance is lower than the order total. Top up and retry.",
                      "required_usd": 26.47,
                      "balance_usd": 4.75,
                      "settled_usd": 4.75
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Not permitted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "external_buy_disabled": {
                    "summary": "Kill-switch off",
                    "value": {
                      "code": "external_buy_disabled",
                      "detail": "This endpoint is currently disabled."
                    }
                  },
                  "trading_not_enabled": {
                    "summary": "Buying off for key",
                    "value": {
                      "code": "trading_not_enabled",
                      "detail": "Enable buying for this key in your profile."
                    }
                  },
                  "account_restricted": {
                    "summary": "Account not eligible",
                    "value": {
                      "code": "account_restricted",
                      "detail": "This endpoint requires a reversal-clean account."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "item_unavailable": {
                    "summary": "Item sold out",
                    "value": {
                      "code": "item_unavailable",
                      "detail": "One or more items are no longer available.",
                      "unavailable_ids": [
                        "itm_8841999"
                      ]
                    }
                  },
                  "price_moved": {
                    "summary": "Live price exceeded ceiling",
                    "value": {
                      "code": "price_moved",
                      "detail": "Live total exceeds max_price_usd.",
                      "quoted_max_usd": 30.0,
                      "current_total_usd": 31.2,
                      "items": [
                        {
                          "id": "itm_8841201",
                          "market_hash_name": "AK-47 | Redline (Minimal Wear)",
                          "price_usd": 15.1
                        }
                      ]
                    }
                  },
                  "idempotency_in_progress": {
                    "summary": "Earlier request still running",
                    "value": {
                      "code": "idempotency_in_progress",
                      "detail": "A request with this custom_id is still being processed."
                    }
                  },
                  "price_updating": {
                    "summary": "Prices refreshing",
                    "value": {
                      "code": "price_updating",
                      "detail": "Prices are updating; retry shortly."
                    }
                  },
                  "concurrent_update": {
                    "summary": "Lost a concurrent-update race",
                    "value": {
                      "code": "concurrent_update",
                      "detail": "Another order touched the same items at the same moment and this one was rolled back. Nothing was charged — retry."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "description": "The purchase could not be completed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "order_failed",
                  "detail": "The purchase could not be completed."
                }
              }
            }
          },
          "504": {
            "description": "Upstream marketplace did not answer in time. The outcome of the purchase is UNKNOWN — it may still have completed. Do NOT re-send blindly: poll the order list, or re-send the identical custom_id / Idempotency-Key, which replays the original result instead of buying again. A retry sent while the original is still unresolved returns 409 idempotency_in_progress.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "upstream_timeout",
                  "detail": "The marketplace did not answer in time, so the outcome of this purchase is UNKNOWN — it may still have gone through. Do not re-send blindly: poll the order list (or re-send the identical custom_id, which replays rather than buys) before treating it as failed."
                }
              }
            }
          }
        }
      }
    },
    "/p2p/inventory": {
      "get": {
        "tags": [
          "P2P"
        ],
        "summary": "Your inventory, ready to list",
        "description": "Every CS2 item we have seen in your Steam inventory, one row per copy, with whether it can be listed right now and why not. Free — any valid key, no balance requirement. If we hold no current read of your inventory this call starts one and answers `inventory_proof.status = pending`; call again after `retry_after_ms`.",
        "operationId": "getP2PInventory",
        "responses": {
          "200": {
            "description": "Your items and the state of the inventory read.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/P2PInventoryItem"
                      }
                    },
                    "inventory_proof": {
                      "$ref": "#/components/schemas/P2PInventoryProof"
                    }
                  },
                  "required": [
                    "data",
                    "inventory_proof"
                  ]
                },
                "example": {
                  "data": [
                    {
                      "operational_asset_id": "5b0c1f7e-3d2a-4c8e-9a61-2f4d8b7e1c30",
                      "asset_revision": "sha256:fd0e6de607b774aaaf4d9cdb7e014c003ba614b03f0460b01e8c94bce034bac5",
                      "asset_id": "38451927734",
                      "market_hash_name": "AK-47 | Redline (Field-Tested)",
                      "context_id": "2",
                      "listable": true,
                      "reasons": [],
                      "listed": false,
                      "listing_id": null,
                      "listing_status": null,
                      "snapshot_completed_at": "2026-10-02T11:58:03.000Z"
                    },
                    {
                      "operational_asset_id": "c81e2d44-9b07-4f1a-b3d5-6e2a90f4c7b8",
                      "asset_revision": "sha256:a5b10a9006f6ebb68f8b9e81c85b5a6d1bf0f32737fc3f57a597dd01e66e0523",
                      "asset_id": "38451927990",
                      "market_hash_name": "Glock-18 | Water Elemental (Minimal Wear)",
                      "context_id": "16",
                      "listable": false,
                      "reasons": [
                        {
                          "code": "hold_not_ended",
                          "message": "The Steam trade hold has not ended yet."
                        }
                      ],
                      "listed": false,
                      "listing_id": null,
                      "listing_status": null,
                      "snapshot_completed_at": "2026-10-02T11:58:03.000Z"
                    }
                  ],
                  "inventory_proof": {
                    "status": "ready",
                    "completed_at": "2026-10-02T11:58:03.000Z",
                    "asset_count": 2
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden — the key's IP allowlist or an account ban.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "account_banned": {
                    "summary": "Account banned",
                    "value": {
                      "code": "account_banned",
                      "detail": "This account is banned."
                    }
                  },
                  "ip_not_allowed": {
                    "summary": "Request from outside the key's IP allowlist",
                    "value": {
                      "code": "ip_not_allowed",
                      "detail": "This API key is restricted to an IP allowlist and 203.0.113.7 is not on it. Update it at https://csboard.com/profile?tab=api"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/P2PDisabled"
          }
        }
      }
    },
    "/p2p/listings": {
      "get": {
        "tags": [
          "P2P"
        ],
        "summary": "Your P2P listings",
        "description": "Your listings that are on sale or mid-sale, newest first, with the payout a sale credits you. A listing with `needs_resync: true` was taken off the shelf because a full read of your inventory no longer contained the item.",
        "operationId": "getP2PListings",
        "responses": {
          "200": {
            "description": "Your listings.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/P2PListing"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "data": [
                    {
                      "id": "cm1xq8z4k0003ab12cd34ef56",
                      "status": "active",
                      "price_usd": 12.34,
                      "currency": "USD",
                      "commission_usd": 0.25,
                      "seller_payout_usd": 12.09,
                      "market_hash_name": "AK-47 | Redline (Field-Tested)",
                      "item_name": "AK-47 | Redline (Field-Tested)",
                      "asset_id": "38451927734",
                      "operational_asset_id": "5b0c1f7e-3d2a-4c8e-9a61-2f4d8b7e1c30",
                      "float_value": 0.2711,
                      "needs_resync": false,
                      "created_at": "2026-10-02T12:04:11.000Z",
                      "updated_at": "2026-10-02T12:04:11.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden — the key's IP allowlist or an account ban.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "account_banned": {
                    "summary": "Account banned",
                    "value": {
                      "code": "account_banned",
                      "detail": "This account is banned."
                    }
                  },
                  "ip_not_allowed": {
                    "summary": "Request from outside the key's IP allowlist",
                    "value": {
                      "code": "ip_not_allowed",
                      "detail": "This API key is restricted to an IP allowlist and 203.0.113.7 is not on it. Update it at https://csboard.com/profile?tab=api"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/P2PDisabled"
          }
        }
      },
      "post": {
        "tags": [
          "P2P"
        ],
        "summary": "List items on the P2P market",
        "description": "Publish one item, or up to 50 as `{ \"items\": [...] }`. Free — any valid key, no balance requirement. CS2 only.\n\nThe website's seller rules apply: a verified email or linked Telegram, the CSBoard extension or app able to send the trade, Steam Mobile Authenticator, no cooldown or shop lock, and a current read of your inventory. The price may not be under half of our market price for the item; unlike the website there is no way to confirm a lower one over a key.\n\nA single item answers `201` (or `200` with `Idempotent-Replay: true` when it was already published under this key). A batch always answers `200` with a result per item — one item that fails does not stop the others. Counts toward the 30 requests/minute P2P write limit of the key.",
        "operationId": "createP2PListings",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Required, 8–128 characters, unique per publish request. Resending the same request with the same key returns each item that was already published instead of listing it twice. A key reused with a different price or revision answers `409 idempotency_key_mismatch`; after `409 idempotency_key_consumed`, use a new key. A `422 price_below_market` refusal does not spend the key.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/P2PListingRequest"
                  },
                  {
                    "type": "object",
                    "required": [
                      "items"
                    ],
                    "additionalProperties": false,
                    "properties": {
                      "items": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 50,
                        "description": "Each `operational_asset_id` may appear once.",
                        "items": {
                          "$ref": "#/components/schemas/P2PListingRequest"
                        }
                      }
                    }
                  }
                ]
              },
              "examples": {
                "single": {
                  "summary": "One item",
                  "value": {
                    "operational_asset_id": "5b0c1f7e-3d2a-4c8e-9a61-2f4d8b7e1c30",
                    "asset_revision": "sha256:fd0e6de607b774aaaf4d9cdb7e014c003ba614b03f0460b01e8c94bce034bac5",
                    "price_usd": 12.34
                  }
                },
                "batch": {
                  "summary": "Several items",
                  "value": {
                    "items": [
                      {
                        "operational_asset_id": "5b0c1f7e-3d2a-4c8e-9a61-2f4d8b7e1c30",
                        "asset_revision": "sha256:fd0e6de607b774aaaf4d9cdb7e014c003ba614b03f0460b01e8c94bce034bac5",
                        "price_usd": 12.34
                      },
                      {
                        "operational_asset_id": "c81e2d44-9b07-4f1a-b3d5-6e2a90f4c7b8",
                        "asset_revision": "sha256:a5b10a9006f6ebb68f8b9e81c85b5a6d1bf0f32737fc3f57a597dd01e66e0523",
                        "price_usd": 3.5
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Single item published.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/P2PListing"
                },
                "example": {
                  "id": "cm1xq8z4k0003ab12cd34ef56",
                  "status": "active",
                  "price_usd": 12.34,
                  "currency": "USD",
                  "commission_usd": 0.25,
                  "seller_payout_usd": 12.09,
                  "market_hash_name": "AK-47 | Redline (Field-Tested)",
                  "item_name": "AK-47 | Redline (Field-Tested)",
                  "asset_id": "38451927734",
                  "operational_asset_id": "5b0c1f7e-3d2a-4c8e-9a61-2f4d8b7e1c30",
                  "float_value": 0.2711,
                  "needs_resync": false,
                  "created_at": "2026-10-02T12:04:11.000Z",
                  "updated_at": "2026-10-02T12:04:11.000Z"
                }
              }
            }
          },
          "200": {
            "description": "A batch result, or a single item that was already published under this Idempotency-Key (header `Idempotent-Replay: true`).",
            "headers": {
              "Idempotent-Replay": {
                "description": "`true` on a replayed single-item publish.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/P2PBatchResult"
                    },
                    {
                      "$ref": "#/components/schemas/P2PListing"
                    }
                  ]
                },
                "example": {
                  "data": [
                    {
                      "operational_asset_id": "5b0c1f7e-3d2a-4c8e-9a61-2f4d8b7e1c30",
                      "success": true,
                      "replay": false,
                      "listing": {
                        "id": "cm1xq8z4k0003ab12cd34ef56",
                        "status": "active",
                        "price_usd": 12.34,
                        "currency": "USD",
                        "commission_usd": 0.25,
                        "seller_payout_usd": 12.09,
                        "market_hash_name": "AK-47 | Redline (Field-Tested)",
                        "item_name": "AK-47 | Redline (Field-Tested)",
                        "asset_id": "38451927734",
                        "operational_asset_id": "5b0c1f7e-3d2a-4c8e-9a61-2f4d8b7e1c30",
                        "float_value": 0.2711,
                        "needs_resync": false,
                        "created_at": "2026-10-02T12:04:11.000Z",
                        "updated_at": "2026-10-02T12:04:11.000Z"
                      }
                    },
                    {
                      "operational_asset_id": "c81e2d44-9b07-4f1a-b3d5-6e2a90f4c7b8",
                      "success": false,
                      "status": 409,
                      "code": "hold_not_ended",
                      "detail": "The Steam trade hold has not ended yet."
                    }
                  ],
                  "success_count": 1,
                  "total_requested": 2
                }
              }
            }
          },
          "400": {
            "description": "Missing Idempotency-Key, a malformed body, or a seller requirement that is not met.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "idempotency_key_required": {
                    "summary": "No Idempotency-Key header",
                    "value": {
                      "code": "idempotency_key_required",
                      "detail": "Send an Idempotency-Key header (8-128 characters), unique per publish request."
                    }
                  },
                  "invalid_request": {
                    "summary": "Malformed body",
                    "value": {
                      "code": "invalid_request",
                      "detail": "price_usd must be 0.10 to 100000 USD with at most two decimals"
                    }
                  },
                  "no_capable_client": {
                    "summary": "Nothing running that can send the trade",
                    "value": {
                      "code": "no_capable_client",
                      "detail": "Seller has no client able to deliver this item — try again later."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden — a seller rule (`contact_required`, `shop_locked`, `p2p_cooldown`, `p2p_suspended`, `trading_banned`), an account ban, or the key's IP allowlist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "contact_required": {
                    "summary": "No verified email or Telegram to tell you about a sale",
                    "value": {
                      "code": "contact_required",
                      "detail": "Add a verified email or link Telegram so we can tell you when your item sells"
                    }
                  },
                  "shop_locked": {
                    "summary": "Shop locked for unanswered sales",
                    "value": {
                      "code": "shop_locked",
                      "detail": "Your shop is locked for unanswered sales",
                      "locked_until": "2026-10-03T09:00:00.000Z"
                    }
                  },
                  "p2p_cooldown": {
                    "summary": "P2P cooldown",
                    "value": {
                      "code": "p2p_cooldown",
                      "detail": "P2P trading is on cooldown for your account",
                      "cooldown_until": "2026-10-02T18:00:00.000Z"
                    }
                  },
                  "account_banned": {
                    "summary": "Account banned",
                    "value": {
                      "code": "account_banned",
                      "detail": "This account is banned."
                    }
                  },
                  "ip_not_allowed": {
                    "summary": "Request from outside the key's IP allowlist",
                    "value": {
                      "code": "ip_not_allowed",
                      "detail": "This API key is restricted to an IP allowlist and 203.0.113.7 is not on it. Update it at https://csboard.com/profile?tab=api"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "The `operational_asset_id` is not in your synced inventory.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "operational_asset_not_found": {
                    "summary": "Unknown asset",
                    "value": {
                      "code": "operational_asset_not_found",
                      "detail": "Asset not found in your synced inventory."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The item cannot be listed as sent, or the Idempotency-Key conflicts. An item that is not listable answers with the first of its `reasons` codes from `GET /p2p/inventory`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "asset_revision_changed": {
                    "summary": "Item changed since you read it",
                    "value": {
                      "code": "asset_revision_changed",
                      "detail": "Inventory changed; review this listing action again"
                    }
                  },
                  "already_listed": {
                    "summary": "Already on sale",
                    "value": {
                      "code": "already_listed",
                      "detail": "Item already has a publishable listing"
                    }
                  },
                  "snapshot_stale": {
                    "summary": "Inventory read too old — includes inventory_proof to poll",
                    "value": {
                      "code": "snapshot_stale",
                      "detail": "The latest complete inventory proof is out of date — refresh your inventory.",
                      "inventory_proof": {
                        "status": "pending",
                        "started_at": "2026-10-02T12:00:00.000Z",
                        "retry_after_ms": 3000
                      }
                    }
                  },
                  "idempotency_in_progress": {
                    "summary": "Same key still processing",
                    "value": {
                      "code": "idempotency_in_progress",
                      "detail": "A request with this Idempotency-Key is still processing."
                    }
                  },
                  "idempotency_key_mismatch": {
                    "summary": "Key reused with different details",
                    "value": {
                      "code": "idempotency_key_mismatch",
                      "detail": "This Idempotency-Key was already used with different listing details."
                    }
                  },
                  "idempotency_key_consumed": {
                    "summary": "Earlier attempt with this key failed",
                    "value": {
                      "code": "idempotency_key_consumed",
                      "detail": "An earlier attempt with this Idempotency-Key failed. Retry with a new key."
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "The price is under half of our market price for this item. Over a key it cannot be confirmed past — adjust `price_usd` and resend; the Idempotency-Key is not spent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "price_below_market": {
                    "summary": "Under half of market",
                    "value": {
                      "code": "price_below_market",
                      "detail": "price_usd 4 is under the minimum 255.16 for this item (market ~510.32). Listings made with an API key cannot go below it.",
                      "market_usd": 510.32,
                      "floor_usd": 255.16,
                      "price_usd": 4
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/P2PWriteLimited"
          },
          "503": {
            "$ref": "#/components/responses/P2PDisabled"
          }
        }
      }
    },
    "/p2p/listings/{id}": {
      "patch": {
        "tags": [
          "P2P"
        ],
        "summary": "Change a listing's price",
        "description": "Move the asking price of one of your `active` listings. The same floor as publishing applies: a price under half of our market price answers `422 price_below_market`. Counts toward the 30 requests/minute P2P write limit of the key.",
        "operationId": "updateP2PListingPrice",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Listing id from `POST /p2p/listings` or `GET /p2p/listings`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "price_usd"
                ],
                "additionalProperties": false,
                "properties": {
                  "price_usd": {
                    "type": "number",
                    "minimum": 0.1,
                    "maximum": 100000,
                    "multipleOf": 0.01,
                    "description": "Asking price in USD, whole cents (`12.34`; `12.345` is refused, not rounded). It may not be under half of our market price for the item — see `price_below_market`."
                  }
                }
              },
              "example": {
                "price_usd": 11.5
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated listing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/P2PListing"
                },
                "example": {
                  "id": "cm1xq8z4k0003ab12cd34ef56",
                  "status": "active",
                  "price_usd": 11.5,
                  "currency": "USD",
                  "commission_usd": 0.23,
                  "seller_payout_usd": 11.27,
                  "market_hash_name": "AK-47 | Redline (Field-Tested)",
                  "item_name": "AK-47 | Redline (Field-Tested)",
                  "asset_id": "38451927734",
                  "operational_asset_id": "5b0c1f7e-3d2a-4c8e-9a61-2f4d8b7e1c30",
                  "float_value": 0.2711,
                  "needs_resync": false,
                  "created_at": "2026-10-02T12:04:11.000Z",
                  "updated_at": "2026-10-02T13:20:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "A malformed price, or the listing is not `active`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Malformed body",
                    "value": {
                      "code": "invalid_request",
                      "detail": "price_usd must be 0.10 to 100000 USD with at most two decimals"
                    }
                  },
                  "listing_not_active": {
                    "summary": "Sold, mid-sale or removed",
                    "value": {
                      "code": "listing_not_active",
                      "detail": "Can only edit active listings"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden — not your listing, an account ban, or the key's IP allowlist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_owner": {
                    "summary": "Someone else's listing",
                    "value": {
                      "code": "not_owner",
                      "detail": "Not your listing"
                    }
                  },
                  "account_banned": {
                    "summary": "Account banned",
                    "value": {
                      "code": "account_banned",
                      "detail": "This account is banned."
                    }
                  },
                  "ip_not_allowed": {
                    "summary": "Request from outside the key's IP allowlist",
                    "value": {
                      "code": "ip_not_allowed",
                      "detail": "This API key is restricted to an IP allowlist and 203.0.113.7 is not on it. Update it at https://csboard.com/profile?tab=api"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No such listing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "listing_not_found": {
                    "summary": "Not found",
                    "value": {
                      "code": "listing_not_found",
                      "detail": "Listing not found"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "The price is under half of our market price for this item. Over a key it cannot be confirmed past.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "price_below_market": {
                    "summary": "Under half of market",
                    "value": {
                      "code": "price_below_market",
                      "detail": "price_usd 4 is under the minimum 255.16 for this item (market ~510.32). Listings made with an API key cannot go below it.",
                      "market_usd": 510.32,
                      "floor_usd": 255.16,
                      "price_usd": 4
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/P2PWriteLimited"
          },
          "503": {
            "description": "The P2P market, or price changes on it, are switched off.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "p2p_disabled": {
                    "summary": "P2P market unavailable",
                    "value": {
                      "code": "p2p_disabled",
                      "detail": "The P2P market is not available right now."
                    }
                  },
                  "p2p_reprice_disabled": {
                    "summary": "Price changes unavailable",
                    "value": {
                      "code": "p2p_reprice_disabled",
                      "detail": "Price changes are not available right now."
                    }
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "P2P"
        ],
        "summary": "Remove a listing",
        "description": "Take one of your `active` listings off the market. A listing that has already sold or is mid-sale cannot be removed and answers `409 listing_not_active`; removing it twice answers the same. Counts toward the 30 requests/minute P2P write limit of the key.",
        "operationId": "deleteP2PListing",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Listing id from `POST /p2p/listings` or `GET /p2p/listings`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Removed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "cancelled"
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "status"
                  ]
                },
                "example": {
                  "id": "cm1xq8z4k0003ab12cd34ef56",
                  "status": "cancelled"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden — not your listing, an account ban, or the key's IP allowlist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "listing_owner_mismatch": {
                    "summary": "Someone else's listing",
                    "value": {
                      "code": "listing_owner_mismatch",
                      "detail": "Listing belongs to another account"
                    }
                  },
                  "account_banned": {
                    "summary": "Account banned",
                    "value": {
                      "code": "account_banned",
                      "detail": "This account is banned."
                    }
                  },
                  "ip_not_allowed": {
                    "summary": "Request from outside the key's IP allowlist",
                    "value": {
                      "code": "ip_not_allowed",
                      "detail": "This API key is restricted to an IP allowlist and 203.0.113.7 is not on it. Update it at https://csboard.com/profile?tab=api"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No such listing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "listing_not_found": {
                    "summary": "Not found",
                    "value": {
                      "code": "listing_not_found",
                      "detail": "Listing not found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The listing is not `active` any more.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "listing_not_active": {
                    "summary": "Sold, mid-sale or already removed",
                    "value": {
                      "code": "listing_not_active",
                      "detail": "Only active listings can be unpublished"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/P2PWriteLimited"
          },
          "503": {
            "$ref": "#/components/responses/P2PDisabled"
          }
        }
      }
    },
    "/transactions": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Your balance ledger",
        "description": "Every movement on your API balance — purchases, refunds, sales, deposits — newest first, keyset paginated. Use it to reconcile: a failed purchase and its refund are two rows sharing the same `order_id`.",
        "operationId": "getTransactions",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page. 1–100. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "type",
            "in": "query",
            "description": "Filter by movement type.",
            "schema": {
              "type": "string",
              "enum": [
                "purchase",
                "refund",
                "sale",
                "deposit",
                "withdrawal",
                "bonus",
                "fee"
              ]
            }
          },
          {
            "name": "start_unix_time",
            "in": "query",
            "description": "Only entries created at or after this Unix timestamp (seconds).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "end_unix_time",
            "in": "query",
            "description": "Only entries created at or before this Unix timestamp (seconds).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Keyset cursor from a previous response's `meta.next_cursor`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of ledger entries.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Transaction"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "next_cursor": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "per_page": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid query parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List your webhook endpoints",
        "operationId": "listWebhooks",
        "description": "Your registered endpoints with their delivery health — last success, last failure, the endpoint's own error text, and the consecutive-failure counter that drives auto-disable.",
        "responses": {
          "200": {
            "description": "Your endpoints.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string",
                            "format": "uri"
                          },
                          "events": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "order.updated",
                                "sell.updated",
                                "withdrawal.updated",
                                "deposit.updated",
                                "webhook.test"
                              ]
                            },
                            "description": "Subscribed event types. An empty request value means all of them; the response always lists them explicitly."
                          },
                          "enabled": {
                            "type": "boolean"
                          },
                          "description": {
                            "type": "string",
                            "nullable": true
                          },
                          "last_success_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true
                          },
                          "last_failure_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true
                          },
                          "last_error": {
                            "type": "string",
                            "nullable": true,
                            "description": "Verbatim reason the last attempt failed — HTTP status, timeout, or URL rejection."
                          },
                          "consecutive_failures": {
                            "type": "integer",
                            "description": "Reset on any success. At 50 the endpoint is auto-disabled."
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Register a webhook endpoint",
        "operationId": "createWebhook",
        "description": "Register an HTTPS endpoint. The response carries the signing `secret` ONCE — there is no endpoint that returns it again, only `rotate-secret`. Maximum 5 endpoints per account. The URL must be publicly routable: anything resolving to a private, loopback, link-local or CGNAT address is rejected, and re-checked before every send because DNS can be re-pointed after registration.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Public HTTPS endpoint that will receive POSTs."
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "order.updated",
                        "sell.updated",
                        "withdrawal.updated",
                        "deposit.updated",
                        "webhook.test"
                      ]
                    },
                    "description": "Omit or leave empty to receive every event type."
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Your own label, e.g. `prod` or `staging`."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created. `secret` is shown only here.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "allOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "url": {
                              "type": "string",
                              "format": "uri"
                            },
                            "events": {
                              "type": "array",
                              "items": {
                                "type": "string",
                                "enum": [
                                  "order.updated",
                                  "sell.updated",
                                  "withdrawal.updated",
                                  "deposit.updated",
                                  "webhook.test"
                                ]
                              },
                              "description": "Subscribed event types. An empty request value means all of them; the response always lists them explicitly."
                            },
                            "enabled": {
                              "type": "boolean"
                            },
                            "description": {
                              "type": "string",
                              "nullable": true
                            },
                            "last_success_at": {
                              "type": "string",
                              "format": "date-time",
                              "nullable": true
                            },
                            "last_failure_at": {
                              "type": "string",
                              "format": "date-time",
                              "nullable": true
                            },
                            "last_error": {
                              "type": "string",
                              "nullable": true,
                              "description": "Verbatim reason the last attempt failed — HTTP status, timeout, or URL rejection."
                            },
                            "consecutive_failures": {
                              "type": "integer",
                              "description": "Reset on any success. At 50 the endpoint is auto-disabled."
                            },
                            "created_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        },
                        {
                          "type": "object",
                          "properties": {
                            "secret": {
                              "type": "string",
                              "description": "HMAC signing secret, `csb_whsec_…`. Shown once."
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_webhook_url` — not https, embeds credentials, or resolves to a private address."
          },
          "409": {
            "description": "`too_many_webhooks` — 5 endpoints already registered."
          }
        }
      }
    },
    "/webhooks/{id}": {
      "patch": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Update a webhook endpoint",
        "operationId": "updateWebhook",
        "description": "Change the URL, the subscribed events, the label, or enable/disable it. Re-enabling also clears the consecutive-failure counter, so an endpoint that was auto-disabled is not disabled again by its next single hiccup.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "order.updated",
                        "sell.updated",
                        "withdrawal.updated",
                        "deposit.updated",
                        "webhook.test"
                      ]
                    }
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 200
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "url": {
                          "type": "string",
                          "format": "uri"
                        },
                        "events": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "order.updated",
                              "sell.updated",
                              "withdrawal.updated",
                              "deposit.updated",
                              "webhook.test"
                            ]
                          },
                          "description": "Subscribed event types. An empty request value means all of them; the response always lists them explicitly."
                        },
                        "enabled": {
                          "type": "boolean"
                        },
                        "description": {
                          "type": "string",
                          "nullable": true
                        },
                        "last_success_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        },
                        "last_failure_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        },
                        "last_error": {
                          "type": "string",
                          "nullable": true,
                          "description": "Verbatim reason the last attempt failed — HTTP status, timeout, or URL rejection."
                        },
                        "consecutive_failures": {
                          "type": "integer",
                          "description": "Reset on any success. At 50 the endpoint is auto-disabled."
                        },
                        "created_at": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — no such webhook on your account."
          }
        }
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete a webhook endpoint",
        "operationId": "deleteWebhook",
        "description": "Remove the endpoint and its delivery history.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "404": {
            "description": "`not_found`."
          }
        }
      }
    },
    "/webhooks/{id}/test": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Send a test event",
        "operationId": "testWebhook",
        "description": "Delivers a `webhook.test` event synchronously and returns the real HTTP status and error text your server produced. The point is to find out NOW whether your signature check passes and your endpoint answers, instead of inferring it from your own logs.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Attempt result (a failed test is still a 200 here — read `delivered`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "delivered": {
                          "type": "boolean"
                        },
                        "response_status": {
                          "type": "integer",
                          "nullable": true
                        },
                        "error": {
                          "type": "string",
                          "nullable": true
                        },
                        "sent": {
                          "type": "object",
                          "description": "The exact envelope we POSTed."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`."
          }
        }
      }
    },
    "/webhooks/{id}/rotate-secret": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Rotate the signing secret",
        "operationId": "rotateWebhookSecret",
        "description": "Issues a new signing secret and returns it once. Deliveries already queued are signed with whichever secret is current at SEND time, so accept both values for a minute or rotate during a quiet window.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "New secret.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "secret": {
                          "type": "string"
                        },
                        "note": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`."
          }
        }
      }
    },
    "/webhooks/{id}/deliveries": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List delivery attempts",
        "operationId": "listWebhookDeliveries",
        "description": "What we sent, how many times we tried, and what your server answered — including the failed attempts and their error text. This is the self-serve answer to \"did you actually send it?\".",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by delivery state.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "delivered",
                "failed"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "1–100, default 50.",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Most recent attempts first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "event_id": {
                            "type": "string",
                            "description": "Stable per (order, state). Dedupe on this."
                          },
                          "event_type": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "delivered",
                              "failed"
                            ]
                          },
                          "attempts": {
                            "type": "integer"
                          },
                          "response_status": {
                            "type": "integer",
                            "nullable": true
                          },
                          "last_error": {
                            "type": "string",
                            "nullable": true
                          },
                          "next_attempt_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true
                          },
                          "delivered_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "payload": {
                            "type": "object",
                            "description": "The exact envelope we POSTed."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`."
          }
        }
      }
    },
    "/webhooks/{id}/deliveries/{deliveryId}/retry": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Retry a failed delivery",
        "operationId": "retryWebhookDelivery",
        "description": "Re-arms a delivery that exhausted its attempts, with a fresh budget and an immediate first try. The replay path for events lost to an outage on your side.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Re-queued.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`."
          },
          "409": {
            "description": "`already_delivered` — that delivery already succeeded."
          }
        }
      }
    },
    "/stats": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Your own delivery and refund record",
        "operationId": "getStats",
        "description": "Orders you placed, how many were delivered, how many were refunded, and how long delivery actually took — computed from your rows at request time. Held orders you cancelled yourself are excluded from the refund rate: changing your mind before a hold clears is the feature working, not a failure. The rate is null until you have a settled order; we do not invent one from zero samples.",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "description": "Window in days, 1-365 (default 30).",
            "schema": {
              "type": "integer",
              "default": 30,
              "minimum": 1,
              "maximum": 365
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Your record over the window.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "window_days": {
                          "type": "integer"
                        },
                        "since": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "orders_total": {
                          "type": "integer"
                        },
                        "delivered": {
                          "type": "integer"
                        },
                        "refunded": {
                          "type": "integer"
                        },
                        "cancelled_by_you": {
                          "type": "integer",
                          "description": "Held orders you cancelled. Excluded from the rate."
                        },
                        "in_flight": {
                          "type": "integer"
                        },
                        "refund_rate_pct": {
                          "type": "number",
                          "nullable": true,
                          "description": "refunded / (delivered + refunded). Null with no settled orders."
                        },
                        "delivery_minutes": {
                          "type": "object",
                          "properties": {
                            "median": {
                              "type": "number",
                              "nullable": true
                            },
                            "p90": {
                              "type": "number",
                              "nullable": true
                            },
                            "samples": {
                              "type": "integer"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request` — days out of range."
          }
        }
      }
    },
    "/key": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Inspect this key",
        "operationId": "getKey",
        "description": "What this key is allowed to do: its prefix, issue date, rate limit, trading and selling capabilities, and its IP allowlist. Also reports `your_ip` — the address we saw for this request, which is what you need before editing an allowlist from a machine whose egress address you are unsure of.",
        "responses": {
          "200": {
            "description": "Key capabilities.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "key_prefix": {
                          "type": "string",
                          "nullable": true
                        },
                        "issued_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        },
                        "rate_limit_per_min": {
                          "type": "integer"
                        },
                        "trading_enabled": {
                          "type": "boolean"
                        },
                        "selling_enabled": {
                          "type": "boolean"
                        },
                        "allowed_ips": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Empty means unrestricted."
                        },
                        "your_ip": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/key/allowed-ips": {
      "put": {
        "tags": [
          "Account"
        ],
        "summary": "Restrict this key to your own addresses",
        "operationId": "putKeyAllowedIps",
        "description": "Bind the key to a set of addresses or CIDR ranges, v4 or v6. An empty array clears the restriction. Requests from anywhere else are refused with 403 ip_not_allowed.\\n\\nA list that would not admit the calling address is refused rather than applied — setting an allowlist you are not inside is indistinguishable from revoking your own key. The same operation is available from the account panel.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ips"
                ],
                "properties": {
                  "ips": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Addresses or CIDR ranges. Empty clears the restriction. Max 20."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Applied.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "allowed_ips": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "your_ip": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` for a malformed entry, or `would_lock_you_out` when the list excludes the calling address (which is echoed back)."
          }
        }
      }
    },
    "/sell/status": {
      "get": {
        "tags": [
          "Instant Sell"
        ],
        "summary": "Instant Sell status",
        "operationId": "getSellStatus",
        "description": "Feature discovery. Works for every key, whether or not selling is enabled on it.",
        "responses": {
          "200": {
            "description": "Status.",
            "content": {
              "application/json": {
                "example": {
                  "enabled": true,
                  "access": "invite_only",
                  "selling_enabled_for_key": false,
                  "margin": null,
                  "min_item_usd": 1,
                  "max_items_per_order": 250,
                  "max_active_orders": 100000,
                  "hold_days_estimate": 8
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/sell/quotes": {
      "post": {
        "tags": [
          "Instant Sell"
        ],
        "summary": "Quote a Steam inventory",
        "operationId": "createSellQuote",
        "description": "Every item in the seller's inventory that the CSBoard network will buy right now, with the exact USD amount your balance is credited per item. 10 requests per minute per key.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SellQuoteRequest"
              },
              "example": {
                "trade_url": "https://steamcommunity.com/tradeoffer/new/?partner=123456789&token=AbCdEfGh",
                "app_id": 730,
                "split": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Quoted items.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SellQuote"
                },
                "example": {
                  "items": [
                    {
                      "asset_id": "41165110534",
                      "app_id": 730,
                      "market_hash_name": "AK-47 | Redline (Field-Tested)",
                      "price_usd": 48.3,
                      "float": 0.23,
                      "phase": null,
                      "icon_url": null,
                      "offer_group": "a"
                    },
                    {
                      "asset_id": "41165110599",
                      "app_id": 730,
                      "market_hash_name": "Glock-18 | Water Elemental (Minimal Wear)",
                      "price_usd": 13.12,
                      "float": 0.11,
                      "phase": null,
                      "icon_url": null,
                      "offer_group": "b"
                    }
                  ],
                  "expires_at": "2026-10-06T14:04:11Z"
                }
              }
            }
          },
          "400": {
            "description": "Malformed body, or a trade URL that does not resolve to a Steam account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "invalid_trade_url",
                  "detail": "The trade URL is malformed or does not resolve to a Steam account."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Selling is not enabled for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "selling_not_enabled",
                  "detail": "Instant Sell API is granted per-account. Contact support@csboard.com to request access."
                }
              }
            }
          },
          "422": {
            "description": "The game is not open for instant sell on this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "unsupported_game",
                  "detail": "app_id 570 is not open for instant sell on this key. Supported: 730, 252490.",
                  "supported_app_ids": [
                    730,
                    252490
                  ]
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "Instant Sell is switched off right now. Reads keep working.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "sell_disabled",
                  "detail": "Instant Sell API is temporarily disabled."
                }
              }
            }
          }
        }
      }
    },
    "/sell/orders": {
      "post": {
        "tags": [
          "Instant Sell"
        ],
        "summary": "Create a sell order",
        "operationId": "createSellOrder",
        "description": "Sell quoted items. A bot from the CSBoard network sends the seller a Steam trade offer, or several when `split` is true. Send `Idempotency-Key` or `external_id` so a retried request replays the original order instead of selling twice. 5 orders per minute per key.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Request-level replay protection. Falls back to `external_id` when absent.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SellOrderRequest"
              },
              "example": {
                "trade_url": "https://steamcommunity.com/tradeoffer/new/?partner=123456789&token=AbCdEfGh",
                "asset_ids": [
                  "41165110534",
                  "41165110599"
                ],
                "min_total_usd": 60,
                "external_id": "my-shop-order-1017",
                "app_id": 730,
                "split": true
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Order created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SellOrder"
                },
                "example": {
                  "id": "cmgk2x9a10001qs01sell0001",
                  "external_id": "my-shop-order-1017",
                  "app_id": 730,
                  "status": "offer_sent",
                  "currency": "USD",
                  "total_usd": 61.42,
                  "credited_usd": 0,
                  "created_at": "2026-10-06T14:02:11Z",
                  "unhold_at": null,
                  "trade_offer_ids": [
                    "7654321098",
                    "7654321111"
                  ],
                  "offers": [
                    {
                      "offer_group": "a",
                      "trade_offer_id": "7654321098",
                      "status": "offer_sent",
                      "amount_usd": 48.3,
                      "expires_at": "2026-10-06T14:17:11Z",
                      "items": [
                        {
                          "asset_id": "41165110534",
                          "market_hash_name": "AK-47 | Redline (Field-Tested)",
                          "price_usd": 48.3,
                          "status": "offer_sent"
                        }
                      ],
                      "bot": {
                        "name": "CSBoard Bot #4",
                        "avatar": "https://avatars.steamstatic.com/abc_full.jpg",
                        "steam_id": "76561199000000004",
                        "profile_url": "https://steamcommunity.com/profiles/76561199000000004",
                        "level": 30
                      }
                    },
                    {
                      "offer_group": "b",
                      "trade_offer_id": "7654321111",
                      "status": "offer_sent",
                      "amount_usd": 13.12,
                      "expires_at": "2026-10-06T14:17:40Z",
                      "items": [
                        {
                          "asset_id": "41165110599",
                          "market_hash_name": "Glock-18 | Water Elemental (Minimal Wear)",
                          "price_usd": 13.12,
                          "status": "offer_sent"
                        }
                      ],
                      "bot": {
                        "name": "CSBoard Bot #9",
                        "avatar": "https://avatars.steamstatic.com/def_full.jpg",
                        "steam_id": "76561199000000009",
                        "profile_url": "https://steamcommunity.com/profiles/76561199000000009",
                        "level": 24
                      }
                    }
                  ],
                  "fail_reason": null
                }
              }
            }
          },
          "200": {
            "description": "Replay of an order already created with this `Idempotency-Key` or `external_id` (`Idempotent-Replayed: true`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SellOrder"
                }
              }
            }
          },
          "400": {
            "description": "Malformed body or trade URL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "invalid_request",
                  "detail": "asset_ids: Duplicate asset ids are not allowed"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Selling is not enabled for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "selling_not_enabled",
                  "detail": "Instant Sell API is granted per-account. Contact support@csboard.com to request access."
                }
              }
            }
          },
          "409": {
            "description": "The order was refused without side effects: `price_drift` (the total it would book is under your `min_total_usd`), `item_not_in_inventory`, `no_eligible_items`, `active_order_exists`, `too_many_active_orders` or `idempotency_in_progress`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "price_drift",
                  "detail": "The live total dropped below your min_total_usd. Re-quote and retry.",
                  "current_total_usd": 57.9,
                  "min_total_usd": 60
                }
              }
            }
          },
          "422": {
            "description": "The game is not open for instant sell on this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "unsupported_game",
                  "detail": "app_id 570 is not open for instant sell on this key. Supported: 730, 252490.",
                  "supported_app_ids": [
                    730,
                    252490
                  ]
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "Instant Sell is switched off right now. Reads keep working.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "sell_disabled",
                  "detail": "Instant Sell API is temporarily disabled."
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Instant Sell"
        ],
        "summary": "List sell orders",
        "operationId": "listSellOrders",
        "description": "Your sell orders placed through the API, newest first, with keyset pagination. The same envelope and query contract as `GET /v1/orders`. With `external_id` it returns that one order instead of a page.",
        "parameters": [
          {
            "name": "external_id",
            "in": "query",
            "description": "Look up one order by your `external_id`. Returns the order object, not a page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page. 1 to 100. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "start_unix_time",
            "in": "query",
            "description": "Only orders created at or after this Unix timestamp (seconds).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "end_unix_time",
            "in": "query",
            "description": "Only orders created at or before this Unix timestamp (seconds).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by order status.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "offer_sent",
                "received",
                "completed",
                "cancelled",
                "failed"
              ]
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Keyset cursor from a previous response's `meta.next_cursor`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of sell orders, or one order when `external_id` is set.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SellOrder"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "next_cursor": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "per_page": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "next_cursor",
                        "per_page"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                },
                "example": {
                  "data": [
                    {
                      "id": "cmgk2x9a10001qs01sell0001",
                      "external_id": "my-shop-order-1017",
                      "app_id": 730,
                      "status": "offer_sent",
                      "currency": "USD",
                      "total_usd": 61.42,
                      "credited_usd": 0,
                      "created_at": "2026-10-06T14:02:11Z",
                      "unhold_at": null,
                      "trade_offer_ids": [
                        "7654321098",
                        "7654321111"
                      ],
                      "offers": [
                        {
                          "offer_group": "a",
                          "trade_offer_id": "7654321098",
                          "status": "offer_sent",
                          "amount_usd": 48.3,
                          "expires_at": "2026-10-06T14:17:11Z",
                          "items": [
                            {
                              "asset_id": "41165110534",
                              "market_hash_name": "AK-47 | Redline (Field-Tested)",
                              "price_usd": 48.3,
                              "status": "offer_sent"
                            }
                          ],
                          "bot": {
                            "name": "CSBoard Bot #4",
                            "avatar": "https://avatars.steamstatic.com/abc_full.jpg",
                            "steam_id": "76561199000000004",
                            "profile_url": "https://steamcommunity.com/profiles/76561199000000004",
                            "level": 30
                          }
                        },
                        {
                          "offer_group": "b",
                          "trade_offer_id": "7654321111",
                          "status": "offer_sent",
                          "amount_usd": 13.12,
                          "expires_at": "2026-10-06T14:17:40Z",
                          "items": [
                            {
                              "asset_id": "41165110599",
                              "market_hash_name": "Glock-18 | Water Elemental (Minimal Wear)",
                              "price_usd": 13.12,
                              "status": "offer_sent"
                            }
                          ],
                          "bot": {
                            "name": "CSBoard Bot #9",
                            "avatar": "https://avatars.steamstatic.com/def_full.jpg",
                            "steam_id": "76561199000000009",
                            "profile_url": "https://steamcommunity.com/profiles/76561199000000009",
                            "level": 24
                          }
                        }
                      ],
                      "fail_reason": null
                    }
                  ],
                  "meta": {
                    "next_cursor": null,
                    "per_page": 50
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "No such sell order on this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "order_not_found",
                  "detail": "No such sell order on this account."
                }
              }
            }
          },
          "422": {
            "description": "Invalid query parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "invalid_request",
                  "detail": "status must be one of: pending, offer_sent, received, completed, cancelled, failed."
                }
              }
            }
          }
        }
      }
    },
    "/sell/orders/{id}": {
      "get": {
        "tags": [
          "Instant Sell"
        ],
        "summary": "Get a sell order",
        "operationId": "getSellOrder",
        "description": "One of your sell orders, with every trade offer and the status of each item.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The order.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SellOrder"
                },
                "example": {
                  "id": "cmgk2x9a10001qs01sell0001",
                  "external_id": "my-shop-order-1017",
                  "app_id": 730,
                  "status": "offer_sent",
                  "currency": "USD",
                  "total_usd": 61.42,
                  "credited_usd": 0,
                  "created_at": "2026-10-06T14:02:11Z",
                  "unhold_at": null,
                  "trade_offer_ids": [
                    "7654321098",
                    "7654321111"
                  ],
                  "offers": [
                    {
                      "offer_group": "a",
                      "trade_offer_id": "7654321098",
                      "status": "offer_sent",
                      "amount_usd": 48.3,
                      "expires_at": "2026-10-06T14:17:11Z",
                      "items": [
                        {
                          "asset_id": "41165110534",
                          "market_hash_name": "AK-47 | Redline (Field-Tested)",
                          "price_usd": 48.3,
                          "status": "offer_sent"
                        }
                      ],
                      "bot": {
                        "name": "CSBoard Bot #4",
                        "avatar": "https://avatars.steamstatic.com/abc_full.jpg",
                        "steam_id": "76561199000000004",
                        "profile_url": "https://steamcommunity.com/profiles/76561199000000004",
                        "level": 30
                      }
                    },
                    {
                      "offer_group": "b",
                      "trade_offer_id": "7654321111",
                      "status": "offer_sent",
                      "amount_usd": 13.12,
                      "expires_at": "2026-10-06T14:17:40Z",
                      "items": [
                        {
                          "asset_id": "41165110599",
                          "market_hash_name": "Glock-18 | Water Elemental (Minimal Wear)",
                          "price_usd": 13.12,
                          "status": "offer_sent"
                        }
                      ],
                      "bot": {
                        "name": "CSBoard Bot #9",
                        "avatar": "https://avatars.steamstatic.com/def_full.jpg",
                        "steam_id": "76561199000000009",
                        "profile_url": "https://steamcommunity.com/profiles/76561199000000009",
                        "level": 24
                      }
                    }
                  ],
                  "fail_reason": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "No such sell order on this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "order_not_found",
                  "detail": "No such sell order on this account."
                }
              }
            }
          }
        }
      }
    },
    "/sell/orders/{id}/cancel": {
      "post": {
        "tags": [
          "Instant Sell"
        ],
        "summary": "Cancel a sell order",
        "operationId": "cancelSellOrder",
        "description": "Allowed while the order is `pending` or `offer_sent` and no offer has been accepted. Later answers `409 not_cancellable`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The order after cancelling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SellOrder"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "No such sell order on this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "order_not_found",
                  "detail": "No such sell order on this account."
                }
              }
            }
          },
          "409": {
            "description": "The order can no longer be cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "not_cancellable",
                  "detail": "Only pending or offer_sent orders can be cancelled."
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Send your key as a Bearer token on every request: `Authorization: Bearer csb_pub_...`. Generate keys in your CSBoard profile."
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid API key (`missing_api_key` or `invalid_api_key`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": "missing_api_key",
              "detail": "Provide your API key via `Authorization: Bearer csb_pub_…`. Generate one at https://csboard.com/profile?tab=api"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded. Includes a Retry-After header (60 seconds on the per-key limits).",
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": "rate_limit_exceeded",
              "detail": "Rate limit of 100 requests/min exceeded."
            }
          }
        }
      },
      "P2PDisabled": {
        "description": "The P2P market is switched off.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "p2p_disabled": {
                "summary": "P2P market unavailable",
                "value": {
                  "code": "p2p_disabled",
                  "detail": "The P2P market is not available right now."
                }
              }
            }
          }
        }
      },
      "P2PWriteLimited": {
        "description": "More than 30 P2P writes (publish, reprice, remove) in the current minute on this key. Wait `Retry-After` seconds.",
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": "rate_limit_exceeded",
              "detail": "P2P write limit of 30/min exceeded."
            }
          }
        }
      }
    },
    "schemas": {
      "Health": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "example": "ok"
          },
          "groups": {
            "type": "integer",
            "description": "Count of priced item groups."
          },
          "price_list_age_seconds": {
            "type": "integer",
            "description": "Age of the materialized price list, in seconds (freshness)."
          }
        },
        "required": [
          "status",
          "groups",
          "price_list_age_seconds"
        ]
      },
      "Sticker": {
        "type": "object",
        "properties": {
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "image": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "slot": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "maximum": 4
          },
          "wear": {
            "type": [
              "number",
              "null"
            ],
            "description": "Sticker wear 0–1, or null if unscraped."
          }
        },
        "required": [
          "name",
          "image",
          "slot",
          "wear"
        ]
      },
      "Listing": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable listing id. Pass to POST /v1/orders."
          },
          "market_hash_name": {
            "type": "string"
          },
          "wear": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "Factory New",
              "Minimal Wear",
              "Field-Tested",
              "Well-Worn",
              "Battle-Scarred",
              null
            ],
            "description": "Wear bucket. `null` for items without wear, and for Dota 2 / Rust."
          },
          "doppler_phase": {
            "type": [
              "string",
              "null"
            ],
            "description": "Doppler / Gamma Doppler phase, e.g. \"Phase 2\", \"Ruby\", or null."
          },
          "float_value": {
            "type": [
              "number",
              "null"
            ],
            "description": "Float value between 0 and 1. `null` when not applicable."
          },
          "paint_seed": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Paint seed (pattern index). `null` when not applicable."
          },
          "stickers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Sticker"
            },
            "description": "Applied stickers; `[]` when none."
          },
          "price_usd": {
            "type": "number",
            "description": "Authoritative asking price in USD. Equals the amount charged if you buy this listing."
          },
          "category": {
            "type": [
              "string",
              "null"
            ],
            "description": "Item category, e.g. `Rifle`, `Knife`, `Gloves`."
          },
          "rarity": {
            "type": [
              "string",
              "null"
            ],
            "description": "Rarity tier, e.g. `Classified`, `Covert`."
          },
          "image": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "Item image URL."
          },
          "inspect_link": {
            "type": [
              "string",
              "null"
            ],
            "description": "Steam inspect link. `null` when there is none, and for Dota 2 / Rust."
          },
          "tradable": {
            "type": "boolean",
            "description": "`false` while the item is inside a Steam trade lock."
          },
          "tradable_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the item leaves trade hold. Null if already tradable."
          },
          "delivery": {
            "type": "string",
            "enum": [
              "instant",
              "up_to_12h",
              "hold"
            ],
            "description": "Delivery bucket: `instant` — bot delivery, seconds to a few minutes; `up_to_12h` — a human seller has to send the trade; `hold` — inside a Steam trade lock until `tradable_at`."
          },
          "refund_percent": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0,
            "maximum": 100,
            "description": "How much of the purchase comes back if Valve reverses the Steam trade, 0–100. A property of the market the listing came from, not a support policy. `null` means we have no published figure — treat it as unknown, never as 100. Filter with `min_refund_percent`."
          },
          "listed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When this item entered the catalogue. Not the same as when the row was created: items return to the catalogue constantly (cancelled orders, expired trade offers, released holds), and a re-listed item is new to you even though it existed before. `sort=newest` orders by this field, and it is the value to feed back as `available_after`.",
            "example": "2026-07-27T09:14:02.481Z"
          }
        },
        "required": [
          "id",
          "market_hash_name",
          "price_usd",
          "category",
          "delivery",
          "stickers",
          "tradable"
        ],
        "description": "One buyable listing. Dota 2 and Rust listings (`appId` 570 / 252490) carry the same keys as CS2 ones; the CS2-only fields — `wear`, `doppler_phase`, `float_value`, `paint_seed`, `inspect_link`, `tradable_at`, `listed_at` — are `null` and `stickers` is `[]`."
      },
      "PriceRow": {
        "type": "object",
        "properties": {
          "market_hash_name": {
            "type": "string"
          },
          "wear": {
            "type": [
              "string",
              "null"
            ]
          },
          "doppler_phase": {
            "type": [
              "string",
              "null"
            ]
          },
          "min_price_usd": {
            "type": "number",
            "description": "Cheapest current ask in USD."
          },
          "qty": {
            "type": "integer",
            "description": "How many are listed at or above this group."
          }
        },
        "required": [
          "market_hash_name",
          "min_price_usd",
          "qty"
        ],
        "description": "One min-ask group. For Dota 2 and Rust (`appId` 570 / 252490) a group is one `market_hash_name`; `wear` and `doppler_phase` are `null`."
      },
      "Currency": {
        "type": "object",
        "properties": {
          "base": {
            "type": "string",
            "example": "USD"
          },
          "rates": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            },
            "description": "Currency code → units per 1 USD."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "rub_source": {
            "type": "string"
          },
          "base_source": {
            "type": "string"
          }
        },
        "required": [
          "base",
          "rates",
          "updated_at"
        ]
      },
      "OrderRequest": {
        "type": "object",
        "properties": {
          "item_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "maxItems": 10,
            "uniqueItems": true,
            "description": "1–10 unique ids from /v1/listings. Some items can't be combined in a single order — if so the order is rejected and you can split it."
          },
          "max_price_usd": {
            "type": "number",
            "description": "Total ceiling in USD. Strongly recommended — your overcharge protection, enforced atomically inside the locked debit.",
            "exclusiveMinimum": 0,
            "maximum": 1000000
          },
          "idempotency_key": {
            "type": "string",
            "description": "Optional; or send the Idempotency-Key header. Replays the original order on retry.",
            "minLength": 8,
            "maxLength": 128
          },
          "autoclaim": {
            "type": "boolean",
            "description": "Sticky per-account setting (not per-order). Send `true` once to switch your key into auto-claim mode: every held order is then auto-released the moment its hold clears (your bot must auto-accept the Steam trade offer within ~15 minutes). Send `false` to switch back to manual claiming via `POST /orders/{id}/claim`. Omit to leave the setting unchanged."
          },
          "appId": {
            "type": "integer",
            "enum": [
              730,
              570,
              252490
            ],
            "default": 730,
            "description": "Game the `item_ids` belong to: `730` = CS2 (the default), `570` = Dota 2, `252490` = Rust. Send the same `appId` you read the ids with from `GET /listings`. A game this key may not buy in answers `400 unsupported_game` — `tradable` in `GET /games` tells you in advance."
          }
        },
        "required": [
          "item_ids"
        ]
      },
      "OrderCreated": {
        "type": "object",
        "description": "The order as it stands the moment it was created. `status` here is the internal state at that instant (for example `paid` or `pending_delivery`), not the normalised vocabulary of `GET /orders` — read the order there, or subscribe to webhooks, to follow it.",
        "properties": {
          "order_id": {
            "type": "string",
            "description": "Order id. Use it with `GET /orders/{id}`."
          },
          "status": {
            "type": "string",
            "description": "Internal order state when the response was built, e.g. `paid` or `pending_delivery`. Poll `GET /orders/{id}` for the public `status`."
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD"
            ]
          },
          "charged_total_usd": {
            "type": "number",
            "description": "Total debited from your balance, in USD."
          },
          "item_count": {
            "type": "integer",
            "description": "Number of items in the order."
          },
          "items": {
            "type": "array",
            "description": "One entry per item bought.",
            "items": {
              "type": "object",
              "properties": {
                "market_hash_name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "price_usd": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "What this item was charged, in USD."
                },
                "status": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Internal item state, if one is set yet; usually `null` right after purchase."
                }
              }
            }
          },
          "delivery": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "instant",
              "pending",
              null
            ],
            "description": "How the order is being delivered, when known: `instant` (bot delivery) or `pending` (a seller or supplier still has to send the trade). Dota 2 and Rust orders always answer `pending`."
          },
          "expected_minutes": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Rough delivery estimate in minutes, when we can state one. Always `null` for Dota 2 and Rust orders."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "order_id",
          "status",
          "currency",
          "charged_total_usd",
          "delivery",
          "expected_minutes"
        ]
      },
      "Balance": {
        "type": "object",
        "properties": {
          "currency": {
            "type": "string",
            "example": "USD"
          },
          "balance_usd": {
            "type": "number",
            "description": "Total balance in USD."
          },
          "trading_enabled": {
            "type": "boolean",
            "description": "Whether buying is enabled for this key."
          },
          "settled_balance_usd": {
            "type": "number",
            "description": "Portion of the balance that is settled (reversal-safe) and spendable on reversal-safe purchases."
          },
          "held_usd": {
            "type": "number",
            "description": "Portion of the balance currently held."
          },
          "held_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the held portion clears, or null if nothing is held."
          }
        },
        "required": [
          "currency",
          "balance_usd",
          "trading_enabled",
          "settled_balance_usd",
          "held_usd",
          "held_until"
        ]
      },
      "OrderItem": {
        "type": "object",
        "properties": {
          "market_hash_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "price_usd": {
            "type": [
              "number",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "hold",
              "delivering",
              "delivered",
              "returned"
            ]
          },
          "tradable_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the item leaves Steam trade hold, or null."
          },
          "return_reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "trade_timeout",
              "declined",
              "expired",
              "rolled_back",
              "unavailable",
              null
            ],
            "description": "Why the item was returned, if its status is `returned`."
          },
          "steam_trade_offer_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "steam_trade_offer_finished_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "status"
        ]
      },
      "Order": {
        "type": "object",
        "properties": {
          "order_id": {
            "type": "string"
          },
          "steam_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "completed",
              "hold",
              "delivering",
              "pending",
              "cancelled",
              "failed"
            ]
          },
          "custom_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Your own id, if you set one at purchase time."
          },
          "currency": {
            "type": "string",
            "example": "USD"
          },
          "charged_total_usd": {
            "type": "number"
          },
          "item_count": {
            "type": "integer"
          },
          "hold_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "refund": {
            "description": "Refund credited for this order, or `null` if none. A `cancelled` or `failed` order is ALWAYS refunded — this field is the receipt, so you never have to infer it from the status or reconcile against your balance.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/Refund"
              },
              {
                "type": "null"
              }
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderItem"
            }
          }
        },
        "required": [
          "order_id",
          "status",
          "currency",
          "charged_total_usd",
          "item_count",
          "created_at",
          "items"
        ]
      },
      "ExternalBuyRequest": {
        "type": "object",
        "properties": {
          "item_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "maxItems": 100,
            "uniqueItems": true,
            "description": "1–100 unique listing ids to buy."
          },
          "partner": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32,
            "description": "Steam trade URL `partner` value. With `token`, forms the destination trade URL."
          },
          "token": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32,
            "description": "Steam trade URL `token` value. With `partner`, forms the destination trade URL."
          },
          "max_price_usd": {
            "type": "number",
            "description": "Total ceiling in USD. Order is rejected with `price_moved` if the live total exceeds it."
          },
          "custom_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "Idempotency key. A retry with the same value replays the original purchase."
          },
          "skip_unavailable": {
            "type": "boolean",
            "default": false,
            "description": "If true, skip items that are no longer available instead of failing the whole request."
          },
          "autoclaim": {
            "type": "boolean",
            "description": "Sticky per-account setting (not per-order). Send `true` once to switch your key into auto-claim mode: every held order is then auto-released the moment its hold clears (your bot must auto-accept the Steam trade offer within ~15 minutes). Send `false` to switch back to manual claiming via `POST /orders/{id}/claim`. Omit to leave the setting unchanged."
          }
        },
        "required": [
          "item_ids",
          "partner",
          "token"
        ]
      },
      "ExternalBuyResult": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "purchase_id": {
                "type": "string"
              },
              "steam_id": {
                "type": "string"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "custom_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "skins": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "price": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "status": {
                      "type": "string"
                    },
                    "return_reason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "steam_trade_offer_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            },
            "required": [
              "purchase_id",
              "steam_id",
              "created_at",
              "skins"
            ]
          }
        },
        "required": [
          "data"
        ]
      },
      "Error": {
        "type": "object",
        "description": "All errors return { code, detail }. Some carry extra fields (e.g. price_moved adds current_total_usd, insufficient_balance adds required_usd/current_usd).",
        "properties": {
          "code": {
            "type": "string",
            "description": "Machine-readable error code, e.g. rate_limit_exceeded, trading_not_enabled, price_moved."
          },
          "detail": {
            "type": "string",
            "description": "Human-readable explanation."
          }
        },
        "required": [
          "code"
        ]
      },
      "Refund": {
        "type": "object",
        "description": "Money credited back to your balance for this order. `null` when nothing was refunded.",
        "properties": {
          "amount_usd": {
            "type": "number",
            "description": "Total credited back, in USD.",
            "example": 1.28
          },
          "refunded_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the last refund credit landed."
          },
          "partial": {
            "type": "boolean",
            "description": "true when only part of the order was refunded (one leg of a multi-item order failed and the rest was delivered).",
            "example": false
          }
        },
        "required": [
          "amount_usd",
          "refunded_at",
          "partial"
        ]
      },
      "Transaction": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Ledger entry id."
          },
          "type": {
            "type": "string",
            "enum": [
              "purchase",
              "refund",
              "sale",
              "deposit",
              "withdrawal",
              "bonus",
              "fee",
              "adjustment"
            ],
            "description": "What moved the money."
          },
          "amount_usd": {
            "type": "number",
            "description": "Signed: negative left your balance, positive came in.",
            "example": -1.28
          },
          "balance_after_usd": {
            "type": "number",
            "description": "Your balance right after this entry.",
            "example": 428.18
          },
          "order_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The order this movement belongs to, or `null` for non-order movements (deposits, bonuses)."
          },
          "order_kind": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "buy",
              "sell",
              null
            ],
            "description": "Whether `order_id` refers to a buy or a sell order."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "type",
          "amount_usd",
          "balance_after_usd",
          "created_at"
        ]
      },
      "Game": {
        "type": "object",
        "properties": {
          "appId": {
            "type": "integer",
            "description": "Steam appId — the value to pass as `appId`.",
            "example": 570
          },
          "name": {
            "type": "string",
            "description": "Display name, e.g. `CS2`, `Dota 2`, `Rust`."
          },
          "tradable": {
            "type": "boolean",
            "description": "Whether this key may also buy in this game (`POST /orders` with this `appId`). `false` means read-only for now."
          }
        },
        "required": [
          "appId",
          "name",
          "tradable"
        ]
      },
      "PublicPrices": {
        "type": "object",
        "properties": {
          "appId": {
            "type": "integer",
            "description": "The game these prices are for.",
            "example": 730
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD"
            ]
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When this payload was built. It is rebuilt at most once a minute."
          },
          "items": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            },
            "description": "`market_hash_name` → the cheapest current ask in USD, rounded to the cent. Keys are sorted. Only names with at least one listing on sale appear. CS2 Doppler and Gamma Doppler phases are merged into Steam's base name and carry the cheapest phase."
          }
        },
        "required": [
          "appId",
          "currency",
          "updatedAt",
          "items"
        ]
      },
      "P2PListingRequest": {
        "type": "object",
        "required": [
          "operational_asset_id",
          "asset_revision",
          "price_usd"
        ],
        "additionalProperties": false,
        "properties": {
          "operational_asset_id": {
            "type": "string",
            "maxLength": 256,
            "description": "The copy to list, from `GET /p2p/inventory`.",
            "example": "5b0c1f7e-3d2a-4c8e-9a61-2f4d8b7e1c30"
          },
          "asset_revision": {
            "type": "string",
            "minLength": 16,
            "maxLength": 128,
            "description": "From `GET /p2p/inventory`, unchanged. If the item changed since you read it, the publish answers `409 asset_revision_changed` — read the inventory again.",
            "example": "sha256:fd0e6de607b774aaaf4d9cdb7e014c003ba614b03f0460b01e8c94bce034bac5"
          },
          "price_usd": {
            "type": "number",
            "minimum": 0.1,
            "maximum": 100000,
            "multipleOf": 0.01,
            "description": "Asking price in USD, whole cents (`12.34`; `12.345` is refused, not rounded). It may not be under half of our market price for the item — see `price_below_market`."
          }
        }
      },
      "P2PListing": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Listing id — use it with `PATCH` / `DELETE /p2p/listings/{id}`."
          },
          "status": {
            "type": "string",
            "description": "`active` — on sale. `trade_pending`, `trade_sent`, `verification_hold` — sold and mid-delivery. `reconciliation_required` — off the shelf because a full inventory read no longer saw the item (`needs_resync: true`)."
          },
          "price_usd": {
            "type": "number",
            "description": "What the buyer pays."
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD"
            ]
          },
          "commission_usd": {
            "type": "number",
            "description": "Our fee on this listing, taken from the seller's side."
          },
          "seller_payout_usd": {
            "type": "number",
            "description": "What a sale credits to your balance: `price_usd` minus `commission_usd`."
          },
          "market_hash_name": {
            "type": "string"
          },
          "item_name": {
            "type": "string"
          },
          "asset_id": {
            "type": "string",
            "description": "Steam asset id of the listed copy."
          },
          "operational_asset_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "float_value": {
            "type": [
              "number",
              "null"
            ]
          },
          "needs_resync": {
            "type": "boolean",
            "description": "`true` when the listing was taken off the shelf because your inventory no longer showed the item. It cannot be revived in place — publish the item again once it is back."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "status",
          "price_usd",
          "currency",
          "commission_usd",
          "seller_payout_usd",
          "market_hash_name",
          "asset_id",
          "needs_resync",
          "created_at",
          "updated_at"
        ],
        "example": {
          "id": "cm1xq8z4k0003ab12cd34ef56",
          "status": "active",
          "price_usd": 12.34,
          "currency": "USD",
          "commission_usd": 0.25,
          "seller_payout_usd": 12.09,
          "market_hash_name": "AK-47 | Redline (Field-Tested)",
          "item_name": "AK-47 | Redline (Field-Tested)",
          "asset_id": "38451927734",
          "operational_asset_id": "5b0c1f7e-3d2a-4c8e-9a61-2f4d8b7e1c30",
          "float_value": 0.2711,
          "needs_resync": false,
          "created_at": "2026-10-02T12:04:11.000Z",
          "updated_at": "2026-10-02T12:04:11.000Z"
        }
      },
      "P2PInventoryProof": {
        "type": [
          "object",
          "null"
        ],
        "description": "Whether we hold a current read of your Steam inventory. Publishing needs `ready`. On `pending`, call `GET /p2p/inventory` again after `retry_after_ms`. On `blocked`, `code` says what to fix on your side.",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ready",
              "pending",
              "blocked"
            ]
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "description": "`ready` only."
          },
          "asset_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "`ready` only."
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "description": "`pending` only."
          },
          "retry_after_ms": {
            "type": "integer",
            "description": "`pending` only — when to ask again."
          },
          "code": {
            "type": "string",
            "description": "`blocked` only: `no_steam_link`, `no_trade_url`, `private_inventory`, `invalid_trade_url`, `empty_inventory`, `inventory_too_large`, `bot_service_unavailable` or `build_timed_out`."
          },
          "message": {
            "type": "string",
            "description": "`blocked` only."
          }
        }
      },
      "P2PInventoryItem": {
        "type": "object",
        "properties": {
          "operational_asset_id": {
            "type": "string",
            "description": "Send this to `POST /p2p/listings`."
          },
          "asset_revision": {
            "type": "string",
            "description": "Send this to `POST /p2p/listings` unchanged."
          },
          "asset_id": {
            "type": "string",
            "description": "Steam asset id — tells two copies of the same skin apart."
          },
          "market_hash_name": {
            "type": "string"
          },
          "context_id": {
            "type": "string",
            "enum": [
              "2",
              "16"
            ],
            "description": "Steam inventory context the copy was seen in."
          },
          "listable": {
            "type": "boolean",
            "description": "`true` when this copy can be published right now."
          },
          "reasons": {
            "type": "array",
            "description": "Why it cannot be published — empty when `listable` is `true`. Typical codes: `snapshot_stale`, `not_tradable`, `on_hold`, `hold_not_ended`, `already_listed`, `reserved`, `active_trade`.",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          },
          "listed": {
            "type": "boolean",
            "description": "Already has a listing."
          },
          "listing_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "listing_status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Status of that listing, as in `P2PListing.status`."
          },
          "snapshot_completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the inventory read that last saw this copy finished."
          }
        }
      },
      "P2PBatchResult": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "One entry per requested item, in request order. On success: `success`, `replay`, `listing`. On failure: `success: false`, `status` and the same `code` / `detail` (plus extras such as `market_usd` / `floor_usd`) the item would have answered on its own.",
              "properties": {
                "operational_asset_id": {
                  "type": "string"
                },
                "success": {
                  "type": "boolean"
                },
                "replay": {
                  "type": "boolean",
                  "description": "`true` when the item was already published under this Idempotency-Key and nothing new was listed."
                },
                "listing": {
                  "$ref": "#/components/schemas/P2PListing"
                },
                "status": {
                  "type": "integer",
                  "description": "On failure: the HTTP status this item alone would have answered."
                },
                "code": {
                  "type": "string"
                },
                "detail": {
                  "type": "string"
                }
              }
            }
          },
          "success_count": {
            "type": "integer"
          },
          "total_requested": {
            "type": "integer"
          }
        }
      },
      "SellQuoteRequest": {
        "type": "object",
        "required": [
          "trade_url"
        ],
        "properties": {
          "trade_url": {
            "type": "string",
            "minLength": 20,
            "maxLength": 300,
            "description": "The seller's Steam trade URL. Their inventory is quoted and the offers are sent here."
          },
          "app_id": {
            "type": "integer",
            "enum": [
              730,
              570,
              252490
            ],
            "default": 730,
            "description": "Steam app to quote: `730` CS2, `570` Dota 2, `252490` Rust. Leave it out for CS2. A game your key cannot sell answers `422 unsupported_game`."
          },
          "split": {
            "type": "boolean",
            "default": false,
            "description": "`false`: the whole sale ships as ONE trade offer. `true`: every item goes to the market that pays most for it, which can mean several offers. See the Instant Sell guide."
          }
        }
      },
      "SellQuoteItem": {
        "type": "object",
        "required": [
          "asset_id",
          "app_id",
          "market_hash_name",
          "price_usd",
          "offer_group"
        ],
        "properties": {
          "asset_id": {
            "type": "string",
            "description": "Steam asset id. Pass it back in `asset_ids` to sell the item."
          },
          "app_id": {
            "type": "integer",
            "description": "Steam app of the item."
          },
          "market_hash_name": {
            "type": "string"
          },
          "price_usd": {
            "type": "number",
            "description": "Exactly what your balance is credited for this item, in USD."
          },
          "float": {
            "type": [
              "number",
              "null"
            ],
            "description": "CS2 float, when known. Always null for Dota 2 and Rust."
          },
          "phase": {
            "type": [
              "string",
              "null"
            ],
            "description": "Reserved. Always null today."
          },
          "icon_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Reserved. Always null today."
          },
          "offer_group": {
            "type": "string",
            "description": "Which trade offer the item rides in if you sell the whole inventory: `a`, `b`, and so on, biggest offer first. Always `a` when `split` is false."
          }
        }
      },
      "SellQuote": {
        "type": "object",
        "required": [
          "items",
          "expires_at"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SellQuoteItem"
            }
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Quotes are good for about two minutes."
          }
        }
      },
      "SellOrderRequest": {
        "type": "object",
        "required": [
          "trade_url",
          "asset_ids"
        ],
        "properties": {
          "trade_url": {
            "type": "string",
            "minLength": 20,
            "maxLength": 300
          },
          "asset_ids": {
            "type": "array",
            "minItems": 1,
            "maxItems": 250,
            "uniqueItems": true,
            "items": {
              "type": "string"
            },
            "description": "Items to sell, from a quote of the same `trade_url`, `app_id` and `split`."
          },
          "min_total_usd": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Your floor for the total this order books. If the total the order would book is lower, it is refused with `409 price_drift` and nothing happens."
          },
          "external_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "Your id for the sale, unique per key. Sending it again returns the original order instead of creating a second one."
          },
          "app_id": {
            "type": "integer",
            "enum": [
              730,
              570,
              252490
            ],
            "default": 730,
            "description": "Must match the quote. Leave it out for CS2."
          },
          "split": {
            "type": "boolean",
            "default": false,
            "description": "Must match the quote. `true` lets the sale ship as several trade offers."
          }
        }
      },
      "SellBot": {
        "type": [
          "object",
          "null"
        ],
        "description": "The Steam account sending this offer. Show it to the seller so they can check the incoming offer.",
        "properties": {
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "avatar": {
            "type": [
              "string",
              "null"
            ]
          },
          "steam_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "profile_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "level": {
            "type": [
              "integer",
              "null"
            ]
          }
        }
      },
      "SellOrderItem": {
        "type": "object",
        "properties": {
          "asset_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "market_hash_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "price_usd": {
            "type": [
              "number",
              "null"
            ],
            "description": "What this item books, in USD."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "offer_sent",
              "received",
              "completed",
              "cancelled",
              "failed"
            ],
            "description": "The status of the offer this item rides in."
          }
        }
      },
      "SellOffer": {
        "type": "object",
        "properties": {
          "offer_group": {
            "type": "string",
            "description": "`a`, `b`, and so on, in the order the offers were created. Matches the quote's `offer_group` when you sell the whole quoted inventory."
          },
          "trade_offer_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Steam trade offer id, once the offer exists."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "offer_sent",
              "received",
              "completed",
              "cancelled",
              "failed"
            ]
          },
          "amount_usd": {
            "type": "number",
            "description": "What this offer books, in USD."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SellOrderItem"
            }
          },
          "bot": {
            "$ref": "#/components/schemas/SellBot"
          }
        }
      },
      "SellOrder": {
        "type": "object",
        "required": [
          "id",
          "app_id",
          "status",
          "currency",
          "total_usd",
          "credited_usd",
          "created_at",
          "trade_offer_ids",
          "offers"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "external_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "app_id": {
            "type": "integer",
            "description": "Steam app of the sale: `730`, `570` or `252490`."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "offer_sent",
              "received",
              "completed",
              "cancelled",
              "failed"
            ]
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD"
            ]
          },
          "total_usd": {
            "type": "number",
            "description": "What the whole order books, in USD."
          },
          "credited_usd": {
            "type": "number",
            "description": "What has already reached your balance. Grows offer by offer."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "unhold_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Latest expected credit time across the offers, once known."
          },
          "trade_offer_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Every Steam trade offer the seller should expect. Offers that never went out are not listed."
          },
          "offers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SellOffer"
            }
          },
          "fail_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "`cancelled_by_merchant`, `offer_declined`, `offer_expired`, `invalid_trade_url`, `item_not_tradable`, `reversed`, `price_drift` or `failed`."
          }
        }
      }
    },
    "parameters": {
      "AppId": {
        "name": "appId",
        "in": "query",
        "required": false,
        "description": "Steam appId of the game. `730` = CS2 (the default), `570` = Dota 2, `252490` = Rust. Omit it and the endpoint answers for CS2 exactly as before. An appId this key may not use answers `400 unsupported_game`, whose `supported_app_ids` lists the ones it may — see `GET /games`.",
        "schema": {
          "type": "integer",
          "enum": [
            730,
            570,
            252490
          ],
          "default": 730
        }
      }
    }
  }
}
