Appearance
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
| Field | Type | Required | Description |
|---|---|---|---|
game_id | number | Yes | Game ID (730, 570, 252490, 440) |
items | array | Yes | Array of items to match (min 1) |
items[].market_hash_name | string | Yes | Steam market hash name |
items[].amount | number | No | Quantity 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
| Field | Type | Description |
|---|---|---|
success | boolean | Whether the request succeeded |
data.buyer_id | string | Matched VIP buyer's identifier. Pass this to /sell/trades/create |
data.items | array | Items with matched prices |
data.items[].market_hash_name | string | Steam market hash name |
data.items[].price | number | Matched buy order price (1$ = 1000) (0 = no match) |
data.items[].amount | number | Matched quantity |
data.items[].error | string | Error 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
| Field | Type | Required | Description |
|---|---|---|---|
custom_id | string | Yes | Your unique trade identifier (used for idempotency) |
buyer_id | string | Yes | Buyer ID returned from /api/sell/match |
tradelink | string | Yes | Your Steam trade offer URL |
game_id | number | Yes | Game ID (730, 570, 252490, 440) |
items | array | Yes | Array of items to sell (min 1) |
items[].assetid | string | Yes | Steam asset ID of the item |
items[].market_hash_name | string | Yes | Steam market hash name |
items[].price | number | Yes | Sale price (1$ = 1000) (must not exceed buy order price) |
items[].contextid | string | No | Steam context ID. Default: "2" |
message | string | No | Optional 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
| Field | Type | Description |
|---|---|---|
success | boolean | Whether the trade was created |
data.trade_id | string | Market trade UUID |
data.custom_id | string | Your custom ID echoed back |
data.summary | object | Trade summary |
data.summary.items_count | number | Number of items in the trade |
data.summary.total_value | number | Total trade value (1$ = 1000) |
data.processed_trade | object | Processed trade details |
data.processed_trade.id | string | Internal trade UUID |
data.processed_trade.status | string | Initial trade status (processing) |
data.selected_bot | object | The bot that will send the trade offer |
data.selected_bot.steamid64 | string | Bot's Steam ID |
data.selected_bot.avatar | string | Bot's avatar URL |
data.selected_bot.profile_name | string | Bot's display name |
data.status | string | Trade status (processing) |
List Trades
GET /api/sell/trades
Retrieve a paginated list of your sell trades with optional filtering and sorting.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
game_id | number | No | Filter by game ID (730, 570, 252490, 440) |
status | string | No | Filter by trade status |
date_from | string | No | Filter trades created after this date (ISO 8601) |
date_to | string | No | Filter trades created before this date (ISO 8601) |
price_min | number | No | Minimum trade value (1$ = 1000) |
price_max | number | No | Maximum trade value (1$ = 1000) |
custom_id | string | No | Filter by your custom trade ID (ILIKE search) |
custom_ids | string | No | Comma-separated list of custom IDs for batch lookup |
trade_ids | string | No | Comma-separated list of market trade UUIDs for batch lookup |
steam_trade_offer_ids | string | No | Comma-separated list of Steam tradeoffer IDs for batch lookup |
steam_trade_ids | string | No | Comma-separated list of Steam full trade IDs for batch lookup |
sort_by | string | No | Sort field (e.g. created_at, purchase_price) |
sort_direction | string | No | Sort direction: asc or desc |
limit | number | No | Number of results per page. Default: 20 |
offset | number | No | Number 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
| Field | Type | Description |
|---|---|---|
data.trades | array | List of trades |
data.trades[].trade_id | string | Market trade UUID |
data.trades[].custom_id | string | Your custom trade ID |
data.trades[].summary | string | Business-level status (see Trade Summary) |
data.trades[].status | string | IMT status (see Trade Statuses) |
data.trades[].created_at | string | null | Trade creation timestamp (ISO 8601) |
data.trades[].updated_at | string | null | Last update timestamp (ISO 8601) |
data.trades[].error | string | null | Error message if trade failed |
data.trades[].processed_trade | object | Processed trade details (see below) |
data.trades[].selected_bot | object | Bot that handled the trade |
data.trades[].selected_bot.steamid64 | string | Bot's Steam ID |
data.trades[].selected_bot.avatar | string | Bot's avatar URL |
data.trades[].selected_bot.profile_name | string | Bot's display name |
data.total | number | Total number of matching trades |
data.limit | number | Page size |
data.offset | number | Current offset |
ProcessedTrade Object
| Field | Type | Description |
|---|---|---|
market | string | Always "market-vpsbot" |
trade_id | string | Steam full trade ID |
tradeoffer_id | string | Steam trade offer ID |
request_id | string | Market trade UUID (same as trade_id at top level) |
partner_id | string | Steam trade offer URL |
items_to_give | array | Items given (always empty for sell trades) |
items_to_receive | array | Items received in the trade |
items_to_receive[].appid | number | Game ID |
items_to_receive[].contextid | string | Steam context ID |
items_to_receive[].assetid | string | Steam asset ID |
items_to_receive[].market_hash_name | string | Item market hash name |
items_to_receive[].amount | string | Always "1" |
status | number | Numeric Steam trade status |
game_id | number | Game ID (730, 570, 252490, 440) |
settlement | string | null | ISO 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
| Parameter | Type | Required | Description |
|---|---|---|---|
game_id | number | No | Filter 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
| Field | Type | Description |
|---|---|---|
data.total_transactions | number | Total number of trades |
data.total_volume | number | Total volume of successful trades (1$ = 1000) |
data.total_revenue | number | Total revenue from successful trades (1$ = 1000) |
data.avg_transaction | number | Average transaction value (1$ = 1000) |
data.success_rate | number | Percentage of successful trades |
data.accepted_count | number | Accepted trades |
data.completed_count | number | Completed trades |
data.processing_count | number | Currently processing trades |
data.error_count | number | Failed trades |
data.cancelled_count | number | Cancelled trades (seller-side failure) |
data.declined_count | number | Declined trades (buyer-side failure) |
data.rolled_back_by_user_count | number | Trades rolled back by the user |
data.rolled_back_by_bot_count | number | Trades 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
| Parameter | Type | Description |
|---|---|---|
custom_id | string | Your 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
| Parameter | Type | Description |
|---|---|---|
tradeoffer_id | string | Steam 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
| Parameter | Type | Description |
|---|---|---|
trade_id | string | Steam 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
| Parameter | Type | Description |
|---|---|---|
id | string | Market 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 Status | Error | Description |
|---|---|---|
| 400 | Invalid request body | Malformed JSON or missing required fields |
Create Trade Errors
| HTTP Status | Error | Description |
|---|---|---|
| 400 | Invalid request body | Malformed JSON or missing required fields |
| 400 | Buyer mismatch | The buyer_id doesn't match the current best buyer for these items |
| 400 | No buy order found for item: ... | An item has no matching buy order |
| 400 | Item ... price exceeds buy order price | Requested price is higher than the active buy order |
| 400 | Trade value must be positive | Total trade value is zero or negative |
| 400 | Insufficient balance | Buyer doesn't have enough balance |
| 400 | No suitable purchase room found | No purchase room matches the trade value |
| 400 | No suitable bot found | No available bot for this trade |
| 400 | Game not supported | The game_id is not supported |
| 409 | A trade with this custom_id already exists | Duplicate custom_id (idempotency check) |
| 500 | Internal error | Server-side failure |
Trade Lookup Errors
| HTTP Status | Error | Description |
|---|---|---|
| 404 | Trade not found | No trade found with the given identifier |
Trade Statuses
Possible values for the status field on sell trades:
| Status | Description |
|---|---|
processing | Trade is being processed (initial status) |
accepted | Trade accepted by both parties |
completed | Trade completed successfully |
declined | Trade declined (buyer-side failure) |
cancelled | Trade cancelled (seller-side failure) |
rolled_back_by_user | Trade rolled back by the user |
rolled_back_by_bot | Trade rolled back by the bot |
Steam Trade Statuses
Possible values for the trade_status field (reflects the Steam trade offer state):
| Status | Description |
|---|---|
Invalid | Trade offer is invalid |
Active | Trade offer is active and awaiting action |
Accepted | Trade offer was accepted |
Countered | Trade offer was countered |
Expired | Trade offer expired |
Canceled | Trade offer was canceled by the sender |
Declined | Trade offer was declined by the recipient |
InvalidItems | Items in the trade are no longer valid |
NeedsConfirmation | Trade needs mobile confirmation |
CanceledBy2FA | Trade was canceled due to 2FA |
InEscrow | Trade is in escrow (trade hold) |
RolledBack | Trade was rolled back by Steam |
MissingItems | Items are missing from the trade |
Sell Flow Overview
- Match - Call
POST /api/sell/matchwith your items to get prices and abuyer_id - Review - Check which items have
price > 0(matched with a buy order) - Create Trade - Call
POST /api/sell/trades/createwith thebuyer_id, your items' asset IDs, and prices - Accept Trade - A bot will send you a Steam trade offer. Accept it to complete the sale
- Track Trade - Use the trade lookup endpoints to monitor trade status (e.g.
GET /api/sell/trades/by-custom-id/{custom_id}) - 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.