Skip to main content
POST
Buy listings from your balance
The orders endpoint lets you buy between 1 and 10 listings in a single atomic request. The charge is debited from your CSBoard balance at the live asking price at the moment of execution — not at the price you saw when you queried /v1/listings. To protect yourself from price movements between lookup and purchase, always include max_price_usd as a total ceiling. The endpoint is idempotent: retrying with the same Idempotency-Key replays the original order rather than creating a duplicate charge. Authentication required. Send your key as Authorization: Bearer csb_pub_.... Trading capability required. The API key must have buying enabled. Configure this in your CSBoard profile.

Prerequisites

Before placing an order, ensure:
  1. Trading-enabled key — buying must be turned on for your API key in your CSBoard profile settings.
  2. Linked Steam account and trade URL — your CSBoard account must have a Steam account connected with a valid trade URL so items can be delivered.
  3. Sufficient balance — your CSBoard balance must cover the total cost of the items at their live prices.

Request headers

string
Optional, 8–128 characters (e.g. a UUID) identifying this order attempt. If you retry a request with the same key, the server answers 200 with the header Idempotent-Replayed: true and the original order response instead of executing a second purchase. While the first request is still running, a retry answers 409 idempotency_in_progress. Use this to safely retry on network timeouts without risk of double-charging.

Request body

string[]
required
Array of 1–10 unique listing IDs to purchase. Obtain these from the id field of GET /v1/listings responses. Each ID must appear only once per request.
number
Total price ceiling in USD, enforced atomically at execution time. If the live total of all items exceeds this value, the entire order is rejected with a price_moved error and you are not charged. Strongly recommended — without it you have no overcharge protection.
string
Alternative to the Idempotency-Key header. If both are provided, the header takes precedence. Use one or the other, not both.
integer
default:"730"
Game the item_ids belong to: 730 = CS2, 570 = Dota 2, 252490 = Rust. Omit it for CS2. Send the same appId you read the ids with from GET /v1/listings. Check tradable in GET /v1/games to see where your key can buy.

Response fields

A new order answers 201 Created. An idempotent replay answers 200 with the same body.
string
required
Unique identifier for this order. Pass it to GET /v1/orders/{id} to follow delivery.
string
required
The order’s internal state when the response was built, for example paid or pending_delivery. This is not the normalised status vocabulary of GET /v1/orders — read the order there, or use webhooks, to follow it.
string
required
Always USD.
number
required
Total debited from your balance, in USD.
integer
Number of items in the order.
object[]
One entry per item bought.
string | null
required
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.
integer | null
required
Rough delivery estimate in minutes, when we can state one. Always null for Dota 2 and Rust orders.
datetime
ISO 8601 timestamp of when the order was created.
datetime | null
ISO 8601 timestamp of the order’s last change.

Example request

Example response

Error codes

Always include max_price_usd in your request. Prices on a live marketplace can change between the moment you query /v1/listings and the moment your order executes. Without this ceiling, your balance could be debited at a higher price than you intended, and there is no automatic rollback.
Items delivered via hold are subject to a Steam trade hold. Check the tradable_at field on the original listing (from GET /v1/listings) to see exactly when a held item will become tradable in your Steam inventory.
Dota 2 and Rust. Orders with appId 570 or 252490 are queued for delivery and answer delivery: "pending" with expected_minutes: null. Follow them with GET /v1/orders/{id}. The price ceiling, balance check and idempotency work exactly as for CS2.

Authorizations

Authorization
string
header
required

Send your key as a Bearer token on every request: Authorization: Bearer csb_pub_.... Generate keys in your CSBoard profile.

Headers

Idempotency-Key
string

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.

Body

application/json
item_ids
string[]
required

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.

Required array length: 1 - 10 elements
max_price_usd
number

Total ceiling in USD. Strongly recommended — your overcharge protection, enforced atomically inside the locked debit.

Required range: x <= 1000000
idempotency_key
string

Optional; or send the Idempotency-Key header. Replays the original order on retry.

Required string length: 8 - 128
autoclaim
boolean

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
enum<integer>
default:730

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.

Available options:
730,
570,
252490

Response

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.

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.

order_id
string
required

Order id. Use it with GET /orders/{id}.

status
string
required

Internal order state when the response was built, e.g. paid or pending_delivery. Poll GET /orders/{id} for the public status.

currency
enum<string>
required
Available options:
USD
charged_total_usd
number
required

Total debited from your balance, in USD.

delivery
enum<string> | null
required

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.

Available options:
instant,
pending,
null
expected_minutes
integer | null
required

Rough delivery estimate in minutes, when we can state one. Always null for Dota 2 and Rust orders.

item_count
integer

Number of items in the order.

items
object[]

One entry per item bought.

created_at
string<date-time>
updated_at
string<date-time> | null