> ## 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/sell/orders: Sell Items from a Steam Inventory

> Sell quoted CS2, Dota 2 or Rust items. CSBoard bots send the seller Steam trade offers and your balance is credited once each offer settles.

Sell items you quoted with [`POST /v1/sell/quotes`](/api-reference/post-sell-quotes). A bot from the CSBoard network sends the seller a Steam trade offer, or several when `split` is `true`. Your balance is credited per offer, once that offer settles. See [when the money arrives](/guides/instant-sell#when-the-money-arrives).

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

**Selling capability required.** Until Instant Sell is enabled for your key this answers `403 selling_not_enabled`.

**Idempotent.** Send an `Idempotency-Key` header, or an `external_id`. A retry with the same value returns the original order with `Idempotent-Replayed: true` instead of selling twice.

## Request body

<ParamField body="trade_url" type="string" required>
  The seller's Steam trade URL. Use the one you quoted.
</ParamField>

<ParamField body="asset_ids" type="string[]" required>
  1 to 250 unique asset ids from the quote.
</ParamField>

<ParamField body="app_id" type="integer" default="730">
  `730` CS2, `570` Dota 2, `252490` Rust. Must match the quote. Leave it out for CS2.
</ParamField>

<ParamField body="split" type="boolean" default="false">
  Must match the quote. `true` lets the sale ship as several trade offers, one per market.
</ParamField>

<ParamField body="min_total_usd" type="number">
  Your floor for what this order books. It is checked against the final total, after the items are grouped into offers. If the total is lower the order is refused with `409 price_drift` and nothing happens. Strongly recommended.
</ParamField>

<ParamField body="external_id" type="string">
  Your id for the sale (1 to 128 characters), unique per key. Retrying with it returns the original order. You can also read the order back with `GET /v1/sell/orders?external_id=`.
</ParamField>

## Response fields

`201` with the sell order. The same object is returned by [`GET /v1/sell/orders/{id}`](/api-reference/get-sell-order), by the list endpoint and in the `sell.updated` webhook.

<ResponseField name="id" type="string" required />

<ResponseField name="external_id" type="string | null" />

<ResponseField name="app_id" type="integer" required>
  Steam app of the sale.
</ResponseField>

<ResponseField name="status" type="string" required>
  `pending`, `offer_sent`, `received`, `completed`, `cancelled` or `failed`. On a sale with several offers, read each offer's own `status` too.
</ResponseField>

<ResponseField name="currency" type="string" required>
  Always `"USD"`.
</ResponseField>

<ResponseField name="total_usd" type="number" required>
  What the whole order books.
</ResponseField>

<ResponseField name="credited_usd" type="number" required>
  What has already reached your balance. It grows offer by offer.
</ResponseField>

<ResponseField name="created_at" type="datetime" required />

<ResponseField name="unhold_at" type="datetime | null">
  The latest expected credit time across the offers, once known.
</ResponseField>

<ResponseField name="trade_offer_ids" type="string[]" required>
  Every Steam trade offer the seller should expect. An offer that never went out is not listed.
</ResponseField>

<ResponseField name="offers" type="SellOffer[]" required>
  One entry per trade offer.

  <Expandable title="SellOffer object">
    <ResponseField name="offer_group" type="string" required>
      `a`, `b` and so on, in the order the offers were created. When you sell the whole quoted inventory it matches the quote's `offer_group`.
    </ResponseField>

    <ResponseField name="trade_offer_id" type="string | null">
      Steam trade offer id, once the offer exists.
    </ResponseField>

    <ResponseField name="status" type="string" required>
      Status of this offer.
    </ResponseField>

    <ResponseField name="amount_usd" type="number" required>
      What this offer books.
    </ResponseField>

    <ResponseField name="expires_at" type="datetime | null" />

    <ResponseField name="items" type="object[]" required>
      `asset_id`, `market_hash_name`, `price_usd` and `status` for each item. An item's `status` is the status of its offer.
    </ResponseField>

    <ResponseField name="bot" type="object | null">
      The Steam account sending the offer: `name`, `avatar`, `steam_id`, `profile_url`, `level`. Show it to the seller so they can check the incoming offer.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="fail_reason" type="string | null">
  `cancelled_by_merchant`, `offer_declined`, `offer_expired`, `invalid_trade_url`, `item_not_tradable`, `reversed`, `price_drift` or `failed`.
</ResponseField>

## Example request

```bash theme={null}
curl -X POST https://csboard.com/v1/sell/orders \
  -H "Authorization: Bearer csb_pub_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: my-shop-order-1017" \
  -d '{
    "trade_url": "https://steamcommunity.com/tradeoffer/new/?partner=123456789&token=AbCdEfGh",
    "asset_ids": ["41165110534", "41165110599"],
    "app_id": 730,
    "split": true,
    "min_total_usd": 60.00,
    "external_id": "my-shop-order-1017"
  }'
```

## Example response

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

## Error codes

| HTTP status | Code | Meaning |
| - | - | - |
| 400 | `invalid_request` | Malformed body: no `asset_ids`, duplicates, more than 250, or an `app_id` outside `730`, `570`, `252490`. |
| 400 | `invalid_trade_url` | The trade URL does not resolve to a Steam account. |
| 400 | `below_min_total` | The order would book less than \$1. |
| 403 | `selling_not_enabled` | Instant Sell is not enabled for this key. |
| 409 | `price_drift` | The total the order would book is below your `min_total_usd`. Includes `current_total_usd` and `min_total_usd`. Re-quote and retry. |
| 409 | `item_not_in_inventory` | An asset id has no live quote. Re-quote and retry. |
| 409 | `no_eligible_items` | None of the items can be sold right now. |
| 409 | `item_not_tradable` | The seller's account has a Steam trade hold. |
| 409 | `active_order_exists` | This seller already has an open offer. Wait for it to finish or cancel it. |
| 409 | `too_many_active_orders` | Too many open sell orders on this key. |
| 409 | `idempotency_in_progress` | A request with this key is still processing. Retry after `Retry-After`. |
| 422 | `unsupported_game` | The game is not open for instant sell on this key. Includes `supported_app_ids`. |
| 429 | `rate_limited` | More than 5 orders per minute on this key. |
| 429 | `daily_cap_exceeded` | The daily sell volume cap for this key is reached. |
| 503 | `sell_disabled` | Instant Sell is switched off right now. |


## OpenAPI

````yaml POST /sell/orders
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:
  /sell/orders:
    post:
      tags:
        - Instant Sell
      summary: Create a sell order
      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.
      operationId: createSellOrder
      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:
        '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'
        '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
        '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.
components:
  schemas:
    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.
    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`.
    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
    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'
    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.
    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'
  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.
  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.