Skip to main content
Selling is the inverse of buying: a user hands CS2 items to a SkinShark-operated Steam bot and their wallet is credited with a payout. You quote the user from our payout book, submit the sale at the exact quote, and the user accepts a single Steam trade offer from the bot. There’s no marketplace listing involved — SkinShark is the counterparty. All three endpoints are sub-user-context, so from a merchant key you send On-Behalf-Of: <subUserId | externalId>. The user must have a linked Steam account — selling always targets their own saved trade URL and can never redirect items elsewhere.

Mental model

The flow

1

Price the sale

Read GET /market/sell/inventory (with On-Behalf-Of) to get the user’s tradable items, each with our USD offer in price. Only items with accepted: true (a quote exists and the item is tradable) can be sold. To price without reading the inventory — e.g. to render a payout table — use GET /market/sell/prices, the raw payout book keyed by marketHashName.
2

Submit the sale

POST /market/sell with the items to sell. Reference each item by its encoded id (from the inventory read) or raw assetid — exactly one — plus the exact price you were quoted. The price is a cent-exact lock: if the quote moved, that submission fails with PRICE_MISMATCH, so re-read and retry. The Trade returns immediately with status initiated. No money moves yet.
3

User accepts the Steam offer

SkinShark picks an available bot and sends the user a receive-only Steam trade offer (the bot gives nothing, only receives). The user must accept it in Steam. Status moves initiated → active once the offer is live.
4

Hold, then payout

After the user accepts, the items sit in Steam’s trade-protection window and the Trade is hold. The payout — one sell_payout from house treasury — is credited once: at hold if your account’s instant-credit setting is on, otherwise at completed when the hold clears. Watch trade.* WebSocket events or poll GET /market/transactions/{id} for the transition.

Status lifecycle

A sell trade uses the same TradeStatus values as a buy, but travels a different path:

Payout timing

The credit is a single ledger post and lands exactly once:
  • Instant credit on — the user is paid at hold, the moment they accept.
  • Instant credit off (default) — the user is paid at completed, when the trade-hold window clears.
settledAt on the Trade marks when the payout posted. totalPrice is the payout in the wallet currency, converted at an FX rate locked at submit time.

Code template

With the TypeScript SDK: client.as(subUserId).market.sell.inventory(), .sell.prices(), and .sell.create(items, externalId).

Errors

Beyond the shared error codes, selling can return: