Skip to content

Sell API

Sell your Steam items to VIP buyers through the matching engine. The sell flow is a two-step process: first match your items against active buy orders, then create a trade with the matched buyer. Use the tracking endpoints to monitor trade progress.

Base path: /api/sell

Match Items

POST /api/sell/match

Match your inventory items against active buy orders. Returns matched prices and the buyer ID. Use this before creating a trade to verify which items have demand and at what price.

Request Body

FieldTypeRequiredDescription
game_idnumberYesGame ID (730, 570, 252490, 440)
itemsarrayYesArray of items to match (min 1)
items[].market_hash_namestringYesSteam market hash name
items[].amountnumberNoQuantity to match. Default: 1
bash
curl -X POST "https://market.vpsbot.io/api/sell/match" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "game_id": 730,
    "items": [
      { "market_hash_name": "AK-47 | Redline (Field-Tested)", "amount": 2 },
      { "market_hash_name": "AWP | Asiimov (Field-Tested)", "amount": 1 }
    ]
  }'
js
const { data } = await client.post('/sell/match', {
  game_id: 730,
  items: [
    { market_hash_name: 'AK-47 | Redline (Field-Tested)', amount: 2 },
    { market_hash_name: 'AWP | Asiimov (Field-Tested)', amount: 1 }
  ]
});

Example Response

json
{
  "success": true,
  "data": {
    "buyer_id": "76561198012345678",
    "items": [
      {
        "market_hash_name": "AK-47 | Redline (Field-Tested)",
        "price": 14500,
        "amount": 2
      },
      {
        "market_hash_name": "AWP | Asiimov (Field-Tested)",
        "price": 32000,
        "amount": 1
      }
    ]
  }
}

TIP

Items with price: 0 have no matching buy order. Only items with a non-zero price can be sold.

Response Fields

FieldTypeDescription
successbooleanWhether the request succeeded
data.buyer_idstringMatched VIP buyer's identifier. Pass this to /sell/trades/create
data.itemsarrayItems with matched prices
data.items[].market_hash_namestringSteam market hash name
data.items[].pricenumberMatched buy order price (1$ = 1000) (0 = no match)
data.items[].amountnumberMatched quantity
data.items[].errorstringError message if item could not be resolved

Create Trade

POST /api/sell/trades/create

Create a sell trade with a matched buyer. This freezes the buyer's balance, assigns a bot, and sends a Steam trade offer to collect your items.

WARNING

You must call /api/sell/match first to obtain the buyer_id and verify item prices. The buyer_id and item prices must match current buy orders, otherwise the request will be rejected.

Request Body

FieldTypeRequiredDescription
custom_idstringYesYour unique trade identifier (used for idempotency)
buyer_idstringYesBuyer ID returned from /api/sell/match
tradelinkstringYesYour Steam trade offer URL
game_idnumberYesGame ID (730, 570, 252490, 440)
itemsarrayYesArray of items to sell (min 1)
items[].assetidstringYesSteam asset ID of the item
items[].market_hash_namestringYesSteam market hash name
items[].pricenumberYesSale price (1$ = 1000) (must not exceed buy order price)
items[].contextidstringNoSteam context ID. Default: "2"
messagestringNoOptional message to include in the trade offer
bash
curl -X POST "https://market.vpsbot.io/api/sell/trades/create" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "custom_id": "sell-001",
    "buyer_id": "76561198012345678",
    "tradelink": "https://steamcommunity.com/tradeoffer/new/?partner=XXXXX&token=YYYYY",
    "game_id": 730,
    "items": [
      {
        "assetid": "38291847562",
        "market_hash_name": "AK-47 | Redline (Field-Tested)",
        "price": 14500
      },
      {
        "assetid": "49382716453",
        "market_hash_name": "AK-47 | Redline (Field-Tested)",
        "price": 14500
      },
      {
        "assetid": "27461938274",
        "market_hash_name": "AWP | Asiimov (Field-Tested)",
        "price": 32000
      }
    ]
  }'
js
const { data } = await client.post('/sell/trades/create', {
  custom_id: 'sell-001',
  buyer_id: '76561198012345678',
  tradelink: 'https://steamcommunity.com/tradeoffer/new/?partner=XXXXX&token=YYYYY',
  game_id: 730,
  items: [
    { assetid: '38291847562', market_hash_name: 'AK-47 | Redline (Field-Tested)', price: 14500 },
    { assetid: '49382716453', market_hash_name: 'AK-47 | Redline (Field-Tested)', price: 14500 },
    { assetid: '27461938274', market_hash_name: 'AWP | Asiimov (Field-Tested)', price: 32000 }
  ]
});

Success Response (201)

json
{
  "success": true,
  "data": {
    "trade_id": "a1b2c3d4-...",
    "custom_id": "sell-001",
    "summary": {
      "items_count": 3,
      "total_value": 61000
    },
    "processed_trade": {
      "id": "a1b2c3d4-...",
      "status": "processing"
    },
    "selected_bot": {
      "steamid64": "76561198999999999",
      "avatar": "https://avatars.steamstatic.com/...",
      "profile_name": "VPSBot #12"
    },
    "status": "processing"
  }
}

Response Fields

FieldTypeDescription
successbooleanWhether the trade was created
data.trade_idstringMarket trade UUID
data.custom_idstringYour custom ID echoed back
data.summaryobjectTrade summary
data.summary.items_countnumberNumber of items in the trade
data.summary.total_valuenumberTotal trade value (1$ = 1000)
data.processed_tradeobjectProcessed trade details
data.processed_trade.idstringInternal trade UUID
data.processed_trade.statusstringInitial trade status (processing)
data.selected_botobjectThe bot that will send the trade offer
data.selected_bot.steamid64stringBot's Steam ID
data.selected_bot.avatarstringBot's avatar URL
data.selected_bot.profile_namestringBot's display name
data.statusstringTrade status (processing)

List Trades

GET /api/sell/trades

Retrieve a paginated list of your sell trades with optional filtering and sorting.

Query Parameters

ParameterTypeRequiredDescription
game_idnumberNoFilter by game ID (730, 570, 252490, 440)
statusstringNoFilter by trade status
date_fromstringNoFilter trades created after this date (ISO 8601)
date_tostringNoFilter trades created before this date (ISO 8601)
price_minnumberNoMinimum trade value (1$ = 1000)
price_maxnumberNoMaximum trade value (1$ = 1000)
custom_idstringNoFilter by your custom trade ID (ILIKE search)
custom_idsstringNoComma-separated list of custom IDs for batch lookup
trade_idsstringNoComma-separated list of market trade UUIDs for batch lookup
steam_trade_offer_idsstringNoComma-separated list of Steam tradeoffer IDs for batch lookup
steam_trade_idsstringNoComma-separated list of Steam full trade IDs for batch lookup
sort_bystringNoSort field (e.g. created_at, purchase_price)
sort_directionstringNoSort direction: asc or desc
limitnumberNoNumber of results per page. Default: 20
offsetnumberNoNumber of results to skip. Default: 0
bash
curl "https://market.vpsbot.io/api/sell/trades?game_id=730&status=accepted&limit=10&offset=0" \
  -H "x-api-key: YOUR_API_KEY"
js
const { data } = await client.get('/sell/trades', {
  params: { game_id: 730, status: 'accepted', limit: 10, offset: 0 }
});

Example Response

json
{
  "success": true,
  "data": {
    "trades": [
      {
        "trade_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "custom_id": "sell-001",
        "summary": "Accepted",
        "processed_trade": {
          "market": "market-vpsbot",
          "trade_id": "4012345678_76561198012345678",
          "tradeoffer_id": "5234567890",
          "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
          "partner_id": "https://steamcommunity.com/tradeoffer/new/?partner=XXXXX&token=YYYYY",
          "items_to_give": [],
          "items_to_receive": [
            {
              "appid": 730,
              "contextid": "2",
              "assetid": "30000000001",
              "market_hash_name": "AK-47 | Redline (Field-Tested)",
              "amount": "1"
            }
          ],
          "status": 3,
          "game_id": 730,
          "settlement": "2026-03-20T10:05:00Z"
        },
        "selected_bot": {
          "steamid64": "76561198000000001",
          "avatar": "https://avatars.steamstatic.com/...",
          "profile_name": "VPSBot #12"
        },
        "status": "accepted",
        "created_at": "2026-03-13T10:00:00Z",
        "updated_at": "2026-03-13T10:05:00Z",
        "error": null
      }
    ],
    "total": 1,
    "limit": 10,
    "offset": 0
  }
}

Response Fields

FieldTypeDescription
data.tradesarrayList of trades
data.trades[].trade_idstringMarket trade UUID
data.trades[].custom_idstringYour custom trade ID
data.trades[].summarystringBusiness-level status (see Trade Summary)
data.trades[].statusstringIMT status (see Trade Statuses)
data.trades[].created_atstring | nullTrade creation timestamp (ISO 8601)
data.trades[].updated_atstring | nullLast update timestamp (ISO 8601)
data.trades[].errorstring | nullError message if trade failed
data.trades[].processed_tradeobjectProcessed trade details (see below)
data.trades[].selected_botobjectBot that handled the trade
data.trades[].selected_bot.steamid64stringBot's Steam ID
data.trades[].selected_bot.avatarstringBot's avatar URL
data.trades[].selected_bot.profile_namestringBot's display name
data.totalnumberTotal number of matching trades
data.limitnumberPage size
data.offsetnumberCurrent offset

ProcessedTrade Object

FieldTypeDescription
marketstringAlways "market-vpsbot"
trade_idstringSteam full trade ID
tradeoffer_idstringSteam trade offer ID
request_idstringMarket trade UUID (same as trade_id at top level)
partner_idstringSteam trade offer URL
items_to_givearrayItems given (always empty for sell trades)
items_to_receivearrayItems received in the trade
items_to_receive[].appidnumberGame ID
items_to_receive[].contextidstringSteam context ID
items_to_receive[].assetidstringSteam asset ID
items_to_receive[].market_hash_namestringItem market hash name
items_to_receive[].amountstringAlways "1"
statusnumberNumeric Steam trade status
game_idnumberGame ID (730, 570, 252490, 440)
settlementstring | nullISO timestamp of when Steam settles the trade (CS2 only)

Trade Dashboard

GET /api/sell/trades/dashboard

Get aggregated statistics for your sell trades.

Query Parameters

ParameterTypeRequiredDescription
game_idnumberNoFilter stats by game ID
bash
curl "https://market.vpsbot.io/api/sell/trades/dashboard?game_id=730" \
  -H "x-api-key: YOUR_API_KEY"
js
const { data } = await client.get('/sell/trades/dashboard', {
  params: { game_id: 730 }
});

Example Response

json
{
  "success": true,
  "data": {
    "total_transactions": 150,
    "total_volume": 6750000,
    "total_revenue": 6750000,
    "avg_transaction": 45000,
    "success_rate": 80.0,
    "accepted_count": 100,
    "completed_count": 20,
    "processing_count": 5,
    "error_count": 3,
    "cancelled_count": 7,
    "declined_count": 5,
    "rolled_back_by_user_count": 8,
    "rolled_back_by_bot_count": 2
  }
}

Response Fields

FieldTypeDescription
data.total_transactionsnumberTotal number of trades
data.total_volumenumberTotal volume of successful trades (1$ = 1000)
data.total_revenuenumberTotal revenue from successful trades (1$ = 1000)
data.avg_transactionnumberAverage transaction value (1$ = 1000)
data.success_ratenumberPercentage of successful trades
data.accepted_countnumberAccepted trades
data.completed_countnumberCompleted trades
data.processing_countnumberCurrently processing trades
data.error_countnumberFailed trades
data.cancelled_countnumberCancelled trades (seller-side failure)
data.declined_countnumberDeclined trades (buyer-side failure)
data.rolled_back_by_user_countnumberTrades rolled back by the user
data.rolled_back_by_bot_countnumberTrades rolled back by the bot

Get Trade by Custom ID

GET /api/sell/trades/by-custom-id/{custom_id}

Look up a trade using your custom identifier.

Path Parameters

ParameterTypeDescription
custom_idstringYour custom trade ID
bash
curl "https://market.vpsbot.io/api/sell/trades/by-custom-id/sell-001" \
  -H "x-api-key: YOUR_API_KEY"
js
const { data } = await client.get('/sell/trades/by-custom-id/sell-001');

Example Response

Returns a single TradeData object. See List Trades for the full schema.


Get Trade by Steam Tradeoffer ID

GET /api/sell/trades/by-steam-tradeoffer-id/{tradeoffer_id}

Look up a trade using the Steam trade offer ID.

Path Parameters

ParameterTypeDescription
tradeoffer_idstringSteam trade offer ID
bash
curl "https://market.vpsbot.io/api/sell/trades/by-steam-tradeoffer-id/5234567890" \
  -H "x-api-key: YOUR_API_KEY"
js
const { data } = await client.get('/sell/trades/by-steam-tradeoffer-id/5234567890');

Example Response

Returns a single TradeData object. See List Trades for the full schema.


Get Trade by Steam Trade ID

GET /api/sell/trades/by-steam-trade-id/{trade_id}

Look up a trade using the Steam trade ID. Only available for trades with status accepted or rolled_back_by_user / rolled_back_by_bot.

Path Parameters

ParameterTypeDescription
trade_idstringSteam trade ID
bash
curl "https://market.vpsbot.io/api/sell/trades/by-steam-trade-id/4012345678" \
  -H "x-api-key: YOUR_API_KEY"
js
const { data } = await client.get('/sell/trades/by-steam-trade-id/4012345678');

Example Response

Returns a single TradeData object. See List Trades for the full schema.


Get Trade by ID

GET /api/sell/trades/by-id/{id}

Look up a trade using its market trade UUID.

Path Parameters

ParameterTypeDescription
idstringMarket trade UUID
bash
curl "https://market.vpsbot.io/api/sell/trades/by-id/a1b2c3d4-..." \
  -H "x-api-key: YOUR_API_KEY"
js
const { data } = await client.get('/sell/trades/by-id/a1b2c3d4-...');

Example Response

Returns a single TradeData object. See List Trades for the full schema.


Error Responses

All endpoints return errors in a consistent format:

json
{
  "success": false,
  "error": "Error description"
}

Match Errors

HTTP StatusErrorDescription
400Invalid request bodyMalformed JSON or missing required fields

Create Trade Errors

HTTP StatusErrorDescription
400Invalid request bodyMalformed JSON or missing required fields
400Buyer mismatchThe buyer_id doesn't match the current best buyer for these items
400No buy order found for item: ...An item has no matching buy order
400Item ... price exceeds buy order priceRequested price is higher than the active buy order
400Trade value must be positiveTotal trade value is zero or negative
400Insufficient balanceBuyer doesn't have enough balance
400No suitable purchase room foundNo purchase room matches the trade value
400No suitable bot foundNo available bot for this trade
400Game not supportedThe game_id is not supported
409A trade with this custom_id already existsDuplicate custom_id (idempotency check)
500Internal errorServer-side failure

Trade Lookup Errors

HTTP StatusErrorDescription
404Trade not foundNo trade found with the given identifier

Trade Statuses

Possible values for the status field on sell trades:

StatusDescription
processingTrade is being processed (initial status)
acceptedTrade accepted by both parties
completedTrade completed successfully
declinedTrade declined (buyer-side failure)
cancelledTrade cancelled (seller-side failure)
rolled_back_by_userTrade rolled back by the user
rolled_back_by_botTrade rolled back by the bot

Steam Trade Statuses

Possible values for the trade_status field (reflects the Steam trade offer state):

StatusDescription
InvalidTrade offer is invalid
ActiveTrade offer is active and awaiting action
AcceptedTrade offer was accepted
CounteredTrade offer was countered
ExpiredTrade offer expired
CanceledTrade offer was canceled by the sender
DeclinedTrade offer was declined by the recipient
InvalidItemsItems in the trade are no longer valid
NeedsConfirmationTrade needs mobile confirmation
CanceledBy2FATrade was canceled due to 2FA
InEscrowTrade is in escrow (trade hold)
RolledBackTrade was rolled back by Steam
MissingItemsItems are missing from the trade

Sell Flow Overview

  1. Match - Call POST /api/sell/match with your items to get prices and a buyer_id
  2. Review - Check which items have price > 0 (matched with a buy order)
  3. Create Trade - Call POST /api/sell/trades/create with the buyer_id, your items' asset IDs, and prices
  4. Accept Trade - A bot will send you a Steam trade offer. Accept it to complete the sale
  5. Track Trade - Use the trade lookup endpoints to monitor trade status (e.g. GET /api/sell/trades/by-custom-id/{custom_id})
  6. Settlement - Once the trade is confirmed on Steam, the buyer's balance is deducted

Idempotency

The custom_id field acts as an idempotency key. If you retry with the same custom_id, you'll get a 409 Conflict instead of a duplicate trade.

Need help? Contact our support team