> ## 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/market/buy — Buy and Deliver to a Steam Trade URL

> Buy up to 100 items and deliver them straight to any Steam trade URL you supply, paid from your settled balance. Built for wholesale and automated delivery.

This endpoint lets you buy and deliver items directly to **any** Steam trade URL you supply — not just the trade URL linked to your account. The trade URL is built from the `partner` and `token` fields. Purchases are funded **only** from your **settled** (reversal-safe) balance, making it suitable for wholesale volume and automated delivery workflows.

The endpoint is **idempotent via the `custom_id` body field**: retrying with the same `custom_id` replays the original purchase rather than buying twice, and the replayed response carries the header `Idempotent-Replayed: true`.

<Warning>
  This endpoint ships behind a kill-switch and requires a trading-enabled, reversal-clean account. When the kill-switch is off it returns `403 external_buy_disabled`.
</Warning>

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

**Trading capability required.** Buying must be enabled for the key, and the account must be reversal-clean.

## Request body

<ParamField body="item_ids" type="string[]" required>
  1–100 unique listing ids to buy.
</ParamField>

<ParamField body="partner" type="string" required>
  Steam trade URL `partner` value (1–32 chars). Together with `token`, forms the destination trade URL items are delivered to.
</ParamField>

<ParamField body="token" type="string" required>
  Steam trade URL `token` value (1–32 chars). Together with `partner`, forms the destination trade URL.
</ParamField>

<ParamField body="max_price_usd" type="number">
  Total price ceiling in USD. If the live total exceeds it, the order is rejected with `price_moved` and nothing is charged. Strongly recommended.
</ParamField>

<ParamField body="custom_id" type="string">
  Idempotency key (1–128 chars). A retry with the same `custom_id` replays the original purchase; the replay response carries `Idempotent-Replayed: true`.
</ParamField>

<ParamField body="skip_unavailable" type="boolean" default="false">
  If `true`, skip items that are no longer available instead of failing the whole request.
</ParamField>

## Response fields

<ResponseField name="data" type="object" required>
  <Expandable title="data object">
    <ResponseField name="purchase_id" type="string" required />

    <ResponseField name="steam_id" type="string" required>
      The Steam ID resolved from the supplied `partner` + `token`.
    </ResponseField>

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

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

    <ResponseField name="skins" type="object[]" required>
      Per-item result.

      <Expandable title="skin object">
        <ResponseField name="name" type="string | null" />

        <ResponseField name="price" type="number | null" />

        <ResponseField name="status" type="string" />

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

        <ResponseField name="steam_trade_offer_id" type="string | null" />
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

## Example request

```bash theme={null}
curl -X POST https://csboard.com/v1/market/buy \
  -H "Authorization: Bearer csb_pub_..." \
  -H "Content-Type: application/json" \
  -d '{
    "item_ids": ["itm_8841201", "itm_8841340"],
    "partner": "447383001",
    "token": "Ab3xZ9Qp",
    "max_price_usd": 30.00,
    "custom_id": "batch-2026-06-29-01",
    "skip_unavailable": false
  }'
```

## Example response

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

## Error codes

| HTTP status | Code                           | Meaning                                                                                         |
| ----------- | ------------------------------ | ----------------------------------------------------------------------------------------------- |
| 400         | `invalid_request`              | Malformed body (e.g. `item_ids` empty or over 100).                                             |
| 400         | `unsupported_item`             | One or more items cannot be delivered via this endpoint (e.g. `ss_live_*` ids).                 |
| 400         | `invalid_trade_url`            | `partner` + `token` do not form a valid Steam trade URL.                                        |
| 401         | `invalid_api_key`              | Missing or invalid API key.                                                                     |
| 402         | `insufficient_settled_balance` | Settled balance below the order total. Includes `required_usd` and `settled_usd`.               |
| 402         | `insufficient_balance`         | Balance below the order total.                                                                  |
| 403         | `external_buy_disabled`        | Kill-switch is off; the endpoint is currently disabled.                                         |
| 403         | `trading_not_enabled`          | Buying is not enabled for this key.                                                             |
| 403         | `account_restricted`           | The endpoint requires a reversal-clean account.                                                 |
| 409         | `item_unavailable`             | One or more items are no longer available. Includes `unavailable_ids[]`.                        |
| 409         | `price_moved`                  | Live total exceeded the ceiling. Includes `quoted_max_usd`, `current_total_usd`, and `items[]`. |
| 409         | `idempotency_in_progress`      | A request with this `custom_id` is still being processed.                                       |
| 409         | `price_updating`               | Prices are refreshing; retry shortly.                                                           |
| 429         | `rate_limit_exceeded`          | Too many requests. Back off for the `Retry-After` header value.                                 |
| 500         | `order_failed`                 | The purchase could not be completed.                                                            |

<Note>
  Funds come exclusively from your **settled** balance. Check `settled_balance_usd` on [`GET /v1/balance`](/api-reference/get-balance) before a large batch, and always send `max_price_usd` as overcharge protection.
</Note>


## OpenAPI

````yaml POST /market/buy
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: Account
    description: Your balance, settled funds, and trading status.
paths:
  /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.
      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
              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: Settled balance too low
                  value:
                    code: insufficient_settled_balance
                    detail: Settled balance is below the order total.
                    required_usd: 26.47
                    settled_usd: 10
                insufficient_balance:
                  summary: Balance too low
                  value:
                    code: insufficient_balance
                    detail: Balance is below the order total.
        '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
                    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.
        '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.
components:
  schemas:
    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.
      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
  responses:
    RateLimited:
      description: Rate limit exceeded. Includes a Retry-After header.
      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
            message: Too many requests.
  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.

````