New features
Buy Dota 2 and Rust with delivery to any trade URLPOST /v1/market/buy now takes appId in the body, like POST /v1/orders: 570 for Dota 2, 252490 for Rust. Leave it out and the endpoint buys CS2, as before.- Payment and delivery work as they do for CS2: settled balance only, and the skins go to the trade URL built from
partner+token. - A Dota 2 or Rust order takes up to 10 ids. More answers
400 too_many_items. - Dota 2 and Rust orders are queued, so every skin answers
pendingfirst. Follow the order withGET /v1/orders/infoor theorder.updatedwebhook.
New features
Instant Sell for Dota 2 and Rust, and sales across several offersPOST /v1/sell/quotesandPOST /v1/sell/orderstakeapp_id:730CS2 (the default),570Dota 2,252490Rust. A game your key cannot sell answers422 unsupported_gamewithsupported_app_ids. Quote items and orders carryapp_id.- New
splitflag. Leave itfalseand the sale ships as one trade offer, to the market that leaves the seller the most value. Set ittrueand every item goes to the market that pays the most for it, which can mean several offers. Quote items carryoffer_group(a,b, and so on) so you know how many offers to expect. - Orders now carry
trade_offer_ids, anoffer_groupon each offer and astatuson each item. Thesell.updatedwebhook sends the same object. - Credit timing per game: CS2 about 7 days after the seller accepts, Dota 2 7 days after the seller accepts, Rust as soon as the market confirms. See when the money arrives.
min_total_usdis now checked against the total the order actually books, after the items are grouped into offers. Below it, the order is refused with409 price_drift.- The Instant Sell endpoints have their own pages in the API reference, including
GET /v1/sell/orderswith list mode and pagination.
sell.updated, withdrawal.updated and deposit.updated with their payloads.New features
Dota 2 and Rust over the same API — choose the game withappIdCSBoard now sells Dota 2 and Rust items as well as CS2, and the API reaches them through one new parameter. Pass Steam’s appId — 570 for Dota 2, 252490 for Rust — and the endpoint answers for that game. Leave it out and you get CS2, byte for byte as before.appIdworks onGET /v1/listings,GET /v1/pricesandGET /v1/listings/availabilityas a query parameter, and onPOST /v1/ordersas a body field.- Dota 2 and Rust rows have the same keys as CS2 rows. The CS2-only fields are
nullandstickersis[], so one parser reads all three games. - CS2-only filters (
wear,min_float,max_float,stat_trak,souvenir,available_after,sort=newest) sent with another game answer400 invalid_paraminstead of being silently ignored. - An
appIdyour key cannot use answers400 unsupported_gamewithsupported_app_ids. New endpointGET /v1/gameslists the games your key can read and whether it can buy there. - Dota 2 and Rust orders answer
delivery: "pending"andexpected_minutes: null.
POST /v1/market/buy stay CS2 only.A keyless price feed: GET /v1/public/pricesGET /v1/public/prices returns one cheapest ask per market_hash_name for CS2, Dota 2 or Rust. It needs no API key and no balance. CS2 Doppler phases are merged into Steam’s base name, so every key matches a real Steam name. The feed is rebuilt once a minute and limited to 1 request per minute per IP.List your own skins on the P2P market from the API — freeFive new endpoints let a key put its owner’s CS2 items up for sale on the CSBoard P2P market. No balance requirement and no trading permission — any valid key works.GET /v1/p2p/inventory— your items, which can be listed now, and why the others cannot.POST /v1/p2p/listings— publish one item or up to 50;Idempotency-Keyrequired.GET /v1/p2p/listings,PATCH /v1/p2p/listings/{id}andDELETE /v1/p2p/listings/{id}— see, reprice and remove them.
422 price_below_market. Over a key it cannot be confirmed past, so a leaked key cannot dump your inventory. Writes are limited to 30 per minute per key. The P2P listing guide walks through the whole flow.Fixes
Purchases that time out now answer504, not 500. When a marketplace stops responding mid-purchase the outcome is genuinely unknown — the buy may still have completed. POST /market/buy and POST /orders now return 504 upstream_timeout for that case and say so explicitly.Crucially, the idempotency claim is held instead of released. Re-sending the identical custom_id / Idempotency-Key replays the original outcome rather than buying a second time; a retry sent while the original is still unresolved returns 409 idempotency_in_progress. Poll the order list before treating a 504 as a failure. Deterministic errors (price moved, insufficient balance, item unavailable) are unchanged.Lost concurrency races answer 409 concurrent_update. When two orders touch the same items at the same instant the loser’s transaction is rolled back whole — nothing charged, nothing reserved. That used to surface as 500; it is now a 409 with Retry-After, because retrying is exactly the right move.New features
Stop polling for new listings — subscribe to themUntil today the only way to notice new inventory was to pollGET /v1/listings harder, and that cost does not divide across clients: ten integrators at 300 requests/minute is ten separate deep scans of the same table returning almost identical rows. Worse, the thing everyone was polling could not answer the question — sort=newest ordered by when the row was created, so items returning to the catalogue from cancelled orders, expired trade offers and released holds never surfaced at the top, no matter how fast anyone polled.Three additions, all backward compatible:- New endpoint
GET /v1/listings/stream— Server-Sent Events. One connection replaces any polling loop, and it emitsgoneevents as well asnewones. That second half is what polling cannot express: a poller only discovers an item sold by trying to buy it and failing. Reconnects are gap-free via the standardLast-Event-IDheader, including across our deploys. - New query parameter
available_afteronGET /v1/listings— turns a poll into a delta read. The usual response is an empty page. Overlap your watermark by ~60 seconds and dedupe byid; the parameter docs explain why that overlap is not optional. - New field
listed_aton everyListing— when the item entered the catalogue, which is whatsort=newestnow orders by. Re-listings surface alongside genuinely new inventory.
sort=newest keeps its name and its ordering direction, it simply stopped hiding re-listings.Fixes
Corrected rate limits in the docsThe published limits were wrong in the direction that costs you throughput: pointed reads are 100 requests/minute, not 30, andPOST /v1/orders is 250/minute, not 30. If you sized your client against the old numbers, you have more headroom than you thought — and if you were about to ask for a raise, try available_after or the stream first.New features
Refunds are now explicit — no more guessingAn order that endscancelled or failed has always been refunded in full, usually within seconds. The API just never said so, which left clients rendering “refund pending” against orders that were already settled. Two additions fix that:- Every order — in
GET /v1/orders,GET /v1/orders/{id}andGET /v1/orders/info— now carries arefundobject:amount_usd,refunded_at, andpartial(true when only one leg of a multi-item order came back). It isnullwhen nothing was refunded. - New endpoint
GET /v1/transactions— your full balance ledger, keyset paginated:purchase,refund,sale,deposit,withdrawal,bonus,fee,adjustment. A purchase and the refund that reversed it share the sameorder_id, so an end-of-day reconciliation is one pass over this feed.
status vocabulary is unchanged, so existing integrations keep working untouched.New features
Instant Sell API (invite-only)Sell CS2 skins programmatically through the CSBoard bot network. Quote a Steam inventory, create a sell order, and funds settle to your CSBoard balance once Steam’s trade-protection hold clears (~8 days).- Quote any Steam inventory with
POST /v1/sell/quotes— every eligible item comes back with the exact USD amount you’ll be credited. - Create orders with
POST /v1/sell/orders, with optionalmin_total_usdprice-drift protection andexternal_ididempotency. - Track lifecycle (
pending→offer_sent→received→completed) and settled amounts withGET /v1/sell/orders/:id. Large baskets can split across up to 3 bots. - Every offer exposes the sending bot’s Steam profile and
trade_offer_idso you can render anti-impersonation checks to sellers. - Access is granted per-account — call
GET /v1/sell/statusto check, and contact support to request access.
Fixes
Precise 402 error codes onPOST /v1/market/buyThe endpoint now distinguishes the two out-of-funds cases instead of always returning insufficient_settled_balance:insufficient_balance— the account balance is simply lower than the order total. Top up and retry.insufficient_settled_balance— the balance covers the total, but part of it is still inside the reversal window and cannot fund external delivery yet.
balance_usd alongside required_usd and settled_usd, so a bot can tell the cases apart programmatically. If your integration matched on the insufficient_settled_balance code for generic low-funds handling, match on HTTP 402 instead.Held orders also gained a small post-unlock grace before claimable flips to true — claiming at the exact unlock instant previously failed on the marketplace side.New features
Claim held orders over the APIOrders that land under a marketplace hold (status: "hold" with a hold_until timestamp) can now be released programmatically. Once hold_until passes, call POST /v1/orders/:id/claim to release the order. After a successful claim the marketplace sends a Steam trade offer your bot must accept within ~15 minutes. Some held orders deliver automatically, in which case the call is a harmless no-op.autoclaim account settingSet autoclaim: true on POST /v1/orders or POST /v1/market/buy and every held order is released automatically the moment its hold clears — no per-order call required. The flag is sticky at the account level.Exact name filter on listings and pricesPass a name query parameter to GET /v1/listings or GET /v1/prices to fetch a single item by its exact market_hash_name (case-insensitive). Unlike search, which does fuzzy word matching and can collide on overlapping titles (for example, Spectrum Case vs Spectrum 2 Case), name returns only the item you asked for. When both parameters are supplied, name takes precedence — no more post-filtering the response.See Market Data for usage examples.