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

# POST /v1/p2p/listings — 在 P2P 市场上架您的 CS2 物品

> 以您自己的价格在 CSBoard P2P 市场上架一件或最多 50 件 CS2 物品。任何 API 密钥均可免费使用；必须提供 Idempotency-Key。

以您自定的价格将您自己的 CS2 物品发布到 CSBoard P2P 市场。可以发送单件物品，也可以用 `{ "items": [...] }` 批量发送最多 50 件。请从 [`GET /v1/p2p/inventory`](/zh-Hans/api-reference/get-p2p-inventory) 获取 `operational_asset_id` 和 `asset_revision`，并原样发送。

**需要身份验证。** 请将密钥作为 `Authorization: Bearer csb_pub_...` 发送。免费——任何有效密钥均可，无余额要求，也无需交易权限。

## 卖家规则

与网站相同的规则同样适用：

* 已验证的邮箱或已绑定的 Telegram，以便在物品售出时通知您；
* CSBoard 扩展程序或应用能够发送 Steam 交易，且账户已启用 Steam 手机令牌；
* 没有 P2P 冷却、暂停或店铺锁定；
* 一份最新的库存读取结果（参见 [`GET /v1/p2p/inventory`](/zh-Hans/api-reference/get-p2p-inventory) 中的 `inventory_proof`）。

## 价格下限

价格不得低于我们对该物品市场价的**一半**。在网站上，卖家在看到警告后可以确认更低的价格；通过 API 密钥则没有这种确认：更低的价格会返回 `422 price_below_market`，并附带 `market_usd` 和 `floor_usd`，方便您调整后重新发送。这种拒绝不会消耗您的 `Idempotency-Key`。如果我们没有该物品的市场价，则不设下限。

价格以美元计，范围 `0.10` 到 `100000`，精确到美分。`12.345` 会被拒绝，而不是被四舍五入。

## 幂等性

`Idempotency-Key` 为**必填**（8–128 个字符，每次发布请求唯一）。如果您用同一个键重新发送同一个请求，已发布的物品会按原样返回，而不会被重复上架。单件物品的重放返回 `200`，并带有 `Idempotent-Replay: true` 响应头。

* 用同一个键发送不同的价格或修订版本，会返回 `409 idempotency_key_mismatch`。
* 收到 `409 idempotency_key_consumed` 表示之前的某次尝试中途失败——请换一个新键重试。

## 响应

* **单件物品：** 返回 `201` 和挂单；重放时返回 `200`。
* **批量：** 始终返回 `200`，`data` 中每件物品一条结果。一件物品失败不会影响其他物品；失败的物品会带上它单独请求时会返回的 `status` 和 `code`。

写操作限制为**每个密钥每分钟 30 次请求**，与改价和下架共用。

## 示例请求

```bash theme={null}
curl -X POST https://csboard.com/v1/p2p/listings \
  -H "Authorization: Bearer csb_pub_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0b7d4c1e-6f2a-4b9e-8c3d-5a1f2e9b7c40" \
  -d '{
    "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
      }
    ]
  }'
```

## 示例响应

```json theme={null}
{
  "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
}
```

## 错误代码

| HTTP 状态码 | 代码 | 含义 |
| - | - | - |
| 400 | `idempotency_key_required` | 缺少 `Idempotency-Key` 请求头，或其长度不在 8–128 个字符之间。 |
| 400 | `invalid_request` | 请求体格式错误——缺少字段、包含未知字段，或价格不在 `0.10`–`100000` 范围内或超过两位小数。 |
| 400 | `no_capable_client` | 您这一侧没有能发送交易的客户端。请运行 CSBoard 扩展程序或应用。 |
| 403 | `contact_required` | 请先添加已验证的邮箱或绑定 Telegram。 |
| 403 | `shop_locked`、`p2p_cooldown`、`p2p_suspended`、`trading_banned` | 该账户的 P2P 出售已被锁定。如果锁定会到期，响应体会注明到期时间。 |
| 403 | `account_banned` / `ip_not_allowed` | 账户已被封禁，或请求来自该密钥 IP 白名单之外的地址。 |
| 404 | `operational_asset_not_found` | `operational_asset_id` 不在您已同步的库存中。 |
| 409 | `asset_revision_changed` | 物品在您读取之后发生了变化。请重新读取库存。 |
| 409 | `snapshot_stale` 及其他 `reasons` 代码 | 该物品不可上架——代码取其 `reasons` 中的第一项。`snapshot_stale` 会附带可供轮询的 `inventory_proof`。 |
| 409 | `already_listed` | 该物品已有挂单。 |
| 409 | `idempotency_in_progress` | 使用该键的请求仍在处理中。请稍候并重新发送同一请求。 |
| 409 | `idempotency_key_mismatch` / `idempotency_key_consumed` | 该键已用于不同的参数，或之前使用它的尝试已失败。请换一个新键。 |
| 422 | `price_below_market` | 价格低于我们市场价的一半。参见 `market_usd` 和 `floor_usd`。 |
| 429 | `rate_limit_exceeded` | 本分钟内 P2P 写操作超过 30 次，或超过该密钥的通用限额。请等待 `Retry-After` 响应头中的秒数。 |
| 503 | `p2p_disabled` | P2P 市场目前已关闭。 |

物品售出后会发生什么，请参阅 [P2P 上架指南](/zh-Hans/guides/p2p-listing)。


## OpenAPI

````yaml POST /p2p/listings
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: 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:
  /p2p/listings:
    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.


        The 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.


        A 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:
        '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
        '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'
        '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'
components:
  schemas:
    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`.
    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
    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'
    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
  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
    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.
    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.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Send your key as a Bearer token on every request: `Authorization: Bearer
        csb_pub_...`. Generate keys in your CSBoard profile.

````

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