Skip to content

Items API ​

Browse, search, and purchase items on the marketplace.

Base path: /api/items

List All Items ​

GET /api/items ​

Returns all items currently for sale. Results are cached for 60 seconds per game_id.

Query Parameters ​

ParameterTypeRequiredDescription
game_idnumberNoGame ID filter. Default: 730
include_holdbooleanNoAlso include trade-locked items. Default: false. Held items are appended with hold: true and an unhold_at ISO timestamp; they are cached separately for 60 seconds. See the Holds API

Headers ​

HeaderDescription
x-api-keyAPI key for authentication
x-inspect-passwordIf provided, sensitive fields (inspect, bot_id) are included

Rate Limit ​

4 requests per minute per user. Response includes X-RateLimit-Limit and X-RateLimit-Remaining headers.

Cache ​

60 seconds per game_id

bash
curl -X GET "https://market.vpsbot.io/api/items?game_id=730" \
  -H "x-api-key: YOUR_API_KEY"
js
const { data } = await client.get('/items', {
  params: { game_id: 730 }
});

Example Response ​

json
{
  "success": true,
  "data": [
    {
      "market_id": "abc123",
      "asset_id": "30000000001",
      "game_id": 730,
      "instanceid": "302028390",
      "classid": "310776560",
      "market_hash_name": "AK-47 | Redline (Field-Tested)",
      "phase": null,
      "float": 0.2531,
      "paint_index": 282,
      "paint_seed": 412,
      "rarity_color": "#D2D2D2",
      "price": 1245,
      "icon_url": "https://steamcdn-a.akamaihd.net/...",
      "stickers": [],
      "inspect": null,
      "bot_id": null,
      "instant_delivery": false,
      "average_delivery_time": 1680,
      "delivery_rate": 98.5
    }
  ]
}

Delivery — average_delivery_time, delivery_rate ​

FieldTypeDescription
average_delivery_timeinteger | nullAverage delivery time, in seconds
delivery_ratenumber | nullDelivery success rate, percent 0–100

Both are null when not available for an item.

The same two fields appear on GET /api/items/:asset_id and on every item body sent over the WebSocket.

Delivery speed — instant_delivery ​

Every catalog item carries an explicit boolean:

ValueMeaning
truestandard delivery — the Steam trade offer is usually created within seconds
falseslower fulfilment — the offer can take minutes up to ~1 hour to arrive

Nothing else about the purchase changes: the buy request, statuses and refund behaviour are identical. For instant_delivery: false items simply poll GET /api/trades (or listen on the WebSocket) until the offer appears.

The value can change over time; the change arrives over the WebSocket like any other item update.

Filtering — instant_delivery query parameter ​

GET /api/items accepts an optional instant_delivery=true|false filter: true returns only near-instant items, false only slower-fulfilment items, and omitting it returns the mixed catalog. The same parameter works on GET /public/prices and the deprecated GetAllItemsOnSale.

bash
curl 'https://market.vpsbot.io/api/items?game_id=730&instant_delivery=true' \
  -H 'x-api-key: YOUR_KEY'

Get Item by Asset ID ​

GET /api/items/:asset_id ​

Returns a single item by its Steam asset ID.

Cached — safe to poll

Responses are served from a 60-second server-side cache that is rewritten the instant any purchase or status change touches the asset (the same computation is pushed as the market-items-changed websocket event). Rapid consecutive requests hit the cache, and a change is visible on the very next request — you never wait out the TTL for purchase-driven changes.

Path Parameters ​

ParameterTypeRequiredDescription
asset_idstringYesSteam asset ID

Headers ​

HeaderDescription
x-api-keyAPI key for authentication
x-inspect-passwordIf provided, sensitive fields are included
bash
curl -X GET "https://market.vpsbot.io/api/items/30000000001" \
  -H "x-api-key: YOUR_API_KEY"
js
const { data } = await client.get('/items/30000000001');

Example Response ​

json
{
  "success": true,
  "data": {
    "market_id": "abc123",
    "asset_id": "30000000001",
    "game_id": 730,
    "market_hash_name": "AK-47 | Redline (Field-Tested)",
    "phase": null,
    "float": 0.2531,
    "price": 1245,
    "icon_url": "https://steamcdn-a.akamaihd.net/...",
    "stickers": [],
    "average_delivery_time": 4,
    "delivery_rate": 100
  }
}

Search Items ​

POST /api/items/search ​

Search items by market hash names or market IDs. At least one search parameter is required.

Request Body ​

FieldTypeRequiredDescription
market_idsstring[]NoArray of internal market IDs
market_hash_namesstring[]NoArray of Steam market hash names
phasesstring[]NoFilter by Doppler phases

WARNING

At least one of market_ids or market_hash_names must be provided.

Rate Limit ​

150 requests per minute per user.

bash
curl -X POST "https://market.vpsbot.io/api/items/search" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "market_hash_names": [
      "AK-47 | Redline (Field-Tested)",
      "AWP | Asiimov (Field-Tested)"
    ]
  }'
js
const { data } = await client.post('/items/search', {
  market_hash_names: [
    'AK-47 | Redline (Field-Tested)',
    'AWP | Asiimov (Field-Tested)'
  ]
});

Example Response ​

json
{
  "success": true,
  "data": [
    {
      "market_id": "abc123",
      "asset_id": "30000000001",
      "game_id": 730,
      "market_hash_name": "AK-47 | Redline (Field-Tested)",
      "phase": null,
      "float": 0.2531,
      "price": 1245,
      "icon_url": "https://steamcdn-a.akamaihd.net/...",
      "stickers": []
    }
  ]
}

Buy Item by Asset ID ​

POST /api/items/buy ​

Purchase a specific item by its asset ID. Deducts the price from your balance and initiates a Steam trade.

Trade-locked items

Items under a Steam trade hold cannot be bought with this endpoint — the purchase is refused with code: "item_on_trade_hold" (see Refused Purchase). Buy them via the Holds API instead.

Request Body ​

FieldTypeRequiredDescription
asset_idstringYesSteam asset ID to purchase
game_idnumberYesGame ID (e.g., 730)
trade_urlstringYesYour Steam trade offer URL
pricenumberYesExpected price (must match current price)
custom_idstring | nullNoYour custom reference ID for this trade
bash
curl -X POST "https://market.vpsbot.io/api/items/buy" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "asset_id": "30000000001",
    "game_id": 730,
    "trade_url": "https://steamcommunity.com/tradeoffer/new/?partner=XXXXX&token=YYYYY",
    "price": 1245,
    "custom_id": "order-001"
  }'
js
const { data } = await client.post('/items/buy', {
  asset_id: '30000000001',
  game_id: 730,
  trade_url: 'https://steamcommunity.com/tradeoffer/new/?partner=XXXXX&token=YYYYY',
  price: 1245,
  custom_id: 'order-001'
});

if (!data.success) {
  // A refused purchase answers HTTP 200: branch on data.code
  console.log(`Purchase refused: ${data.code} (${data.error})`);
}

Example Response ​

json
{
  "success": true,
  "data": {
    "trade_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "steam_trade_id": "5234567890",  // may be null at first — see note below
    "custom_id": "order-001",
    "trade_url": "https://steamcommunity.com/tradeoffer/new/?partner=XXXXX&token=YYYYY",
    "asset_id": "30000000001",
    "market_hash_name": "AK-47 | Redline (Field-Tested)",
    "phase": null,
    "price": 1245,
    "status": "processing",
    "summary": "InProgress",
    "steam_trade_status": "Active"
  }
}

steam_trade_id can be null

The Steam offer is created asynchronously. steam_trade_id may be null in the buy response (and, for some fulfilment paths, stay null in GET /api/trades even after delivery). Track the purchase by trade_id / custom_id and rely on status (processing → accepted → completed), not on the offer id.

Refused Purchase ​

If the purchase cannot go through, it is refused and your balance is not charged: an amount already debited is refunded before the response is sent. The response is HTTP 200 with success: false, a machine-readable code and a human-readable error:

json
{
  "success": false,
  "code": "trade_partner_banned",
  "error": "Your Steam account has a trade ban and cannot receive trade offers"
}
codeerrorMeaning
item_not_foundItem not found or already soldThe item is no longer for sale. On buy-by-name: no item matches the name and phase within max_price
item_unavailableItem is no longer availableThe item was still listed, but the seller can no longer deliver it. Your balance is not charged. Pick another listing
item_on_trade_holdItem is on trade holdThe item is under a Steam trade hold. Buy it via the Holds API
price_changedPrice mismatch: listing price does not match the offered priceThe listing price differs from the price you sent, or it changed while the purchase was being placed. Fetch the current price and retry
insufficient_balanceInsufficient balance to buy the itemYour available balance is below the item price
duplicate_custom_idA trade with this custom_id already existsA purchase with this custom_id already exists. Look it up in GET /api/trades, or send a new custom_id
item_reservedItem is being purchased by another buyer; please retryAnother buyer is purchasing this item right now. Retry shortly
invalid_trade_urlThe trade URL cannot receive trade offersYour trade_url cannot receive trade offers: it is malformed or out of date (regenerate it in Steam), or the account cannot trade right now. Check the URL
trade_partner_bannedYour Steam account has a trade ban and cannot receive trade offersThe Steam account behind your trade_url has a trade ban and cannot receive trade offers. Retrying fails the same way until the ban is lifted
trade_bannedThe bot for this trade has a Steam trade banThe bot holding this item has a Steam trade ban and cannot deliver it. Retrying this item fails the same way while the ban lasts

Check success and code, not the HTTP status

A refused purchase still answers HTTP 200. Always check success, and when it is false, branch on code rather than on the error text. HTTP 4xx / 5xx keep their usual meaning: an invalid request answers 400 with code: "validation_failed", a server failure answers 500 with code: "internal_error". See Response Format.

Hold purchases have their own codes: see Refused Hold Purchase.


Buy Item by Name ​

POST /api/items/buy-by-name ​

Purchase the cheapest available item matching the given market hash name. Useful when you don't care about a specific listing.

Trade-locked items

Items under a Steam trade hold are refused with code: "item_on_trade_hold" — they can only be bought via the Holds API.

Request Body ​

FieldTypeRequiredDescription
market_hash_namestringYesSteam market hash name
game_idnumberYesGame ID (e.g., 730)
phasestring | nullNoDoppler phase filter
trade_urlstringYesYour Steam trade offer URL
max_pricenumberYesMaximum price you're willing to pay
custom_idstring | nullNoYour custom reference ID
bash
curl -X POST "https://market.vpsbot.io/api/items/buy-by-name" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "market_hash_name": "AK-47 | Redline (Field-Tested)",
    "game_id": 730,
    "phase": null,
    "trade_url": "https://steamcommunity.com/tradeoffer/new/?partner=XXXXX&token=YYYYY",
    "max_price": 1500,
    "custom_id": "order-002"
  }'
js
const { data } = await client.post('/items/buy-by-name', {
  market_hash_name: 'AK-47 | Redline (Field-Tested)',
  game_id: 730,
  phase: null,
  trade_url: 'https://steamcommunity.com/tradeoffer/new/?partner=XXXXX&token=YYYYY',
  max_price: 1500,
  custom_id: 'order-002'
});

if (!data.success) {
  // A refused purchase answers HTTP 200: branch on data.code
  console.log(`Purchase refused: ${data.code} (${data.error})`);
}

Example Response ​

json
{
  "success": true,
  "data": {
    "trade_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "steam_trade_id": "5234567891",
    "custom_id": "order-002",
    "trade_url": "https://steamcommunity.com/tradeoffer/new/?partner=XXXXX&token=YYYYY",
    "asset_id": "30000000001",
    "market_hash_name": "AK-47 | Redline (Field-Tested)",
    "phase": null,
    "price": 1245,
    "status": "processing",
    "summary": "InProgress",
    "steam_trade_status": "Active"
  }
}

Refused Purchase ​

Same as POST /api/items/buy: a refused purchase answers HTTP 200 with success: false, a machine-readable code and a human-readable error, with the same codes. When no item matches the name and phase within max_price, the code is item_not_found. Your balance is not charged.


Recently Sold Items ​

GET /api/items/recently-sold ​

Returns asset IDs of items sold in the last 10 seconds. Useful for filtering out unavailable items from your local cache.

Cache ​

10 seconds

bash
curl -X GET "https://market.vpsbot.io/api/items/recently-sold" \
  -H "x-api-key: YOUR_API_KEY"
js
const { data } = await client.get('/items/recently-sold');

Example Response ​

json
{
  "success": true,
  "data": [
    "30000000001",
    "30000000042",
    "30000000099"
  ]
}

Check Availability ​

POST /api/items/check-availability ​

Check if an item can be purchased before attempting to buy.

Request Body ​

FieldTypeRequiredDescription
asset_idstringNoSteam asset ID
market_idstringNoInternal market ID
bash
curl -X POST "https://market.vpsbot.io/api/items/check-availability" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"asset_id": "30000000001"}'
js
const { data } = await client.post('/items/check-availability', {
  asset_id: '30000000001'
});

Example Response ​

json
{
  "success": true,
  "data": {
    "can_buy": true,
    "bot_id": "76561198...",
    "reason": null
  }
}

Every response carries can_hold_buy. For an item under a Steam trade hold that is hold-sellable, can_buy is false but can_hold_buy is true, together with the hold listing price and the unlock timestamp — buy it via the Holds API:

json
{
  "success": true,
  "data": {
    "can_buy": false,
    "can_hold_buy": true,
    "bot_id": "76561199...",
    "reason": "trade_hold",
    "hold_price": 2800,
    "unhold_at": "2026-08-19T07:00:00Z"
  }
}

A trade-locked item without a hold price range set by its seller reports can_hold_buy: false. Regular (unlocked, listed) items report can_buy: true, can_hold_buy: false.

Held items in Get Item by Asset ID

GET /api/items/:asset_id also resolves hold-sellable trade-locked items: instead of a 404 it returns the item with hold: true, unhold_at, and price set to the hold listing price.


Get Item Availability ​

GET /api/items/:asset_id/availability ​

Check whether a specific item is available and not banned.

Path Parameters ​

ParameterTypeRequiredDescription
asset_idstringYesSteam asset ID
bash
curl -X GET "https://market.vpsbot.io/api/items/30000000001/availability" \
  -H "x-api-key: YOUR_API_KEY"
js
const { data } = await client.get('/items/30000000001/availability');

Example Response ​

json
{
  "success": true,
  "data": {
    "asset_id": "30000000001",
    "available": true,
    "banned": false,
    "reason": null
  }
}

Item Object Schema ​

FieldTypeDescription
market_idstring | nullInternal market listing ID
asset_idstringSteam asset ID
game_idnumberGame ID (730, 570, 252490, 440)
instanceidstringSteam instance ID
classidstringSteam class ID
market_hash_namestringSteam market hash name
phasestring | nullDoppler phase (e.g., "Phase 1")
floatnumber | nullFloat value (wear)
paint_indexnumber | nullPaint index
paint_seednumber | nullPaint seed
rarity_colorstring | nullHex color code for rarity
pricenumber | nullPrice (1$ = 1000)
icon_urlstringSteam CDN icon URL
stickersobjectSticker data
inspectstring | nullInspect link (requires x-inspect-password)
bot_idstringBot Steam ID (requires x-inspect-password)
source_idstring | nullFulfilment source: local, an instant-delivery market, or a provider key (requires x-inspect-password)
holdbooleanOptional. true when the item is under a Steam trade hold (only returned with include_hold=true)
unhold_atstringOptional. ISO timestamp of when the trade hold ends (held items only)

Buy Response Fields ​

The buy response includes status fields for tracking the trade lifecycle:

FieldTypeDescription
trade_idstringInternal trade identifier (UUID)
steam_trade_idstring | nullSteam trade offer ID
statusstringIMT status (processing on creation)
summarystringBusiness-level status (InProgress on creation)
steam_trade_statusstring | nullSteam trade status string (e.g. Active)

TIP

For full status reference (all possible status, summary, and steam_trade_status values), see the Trades API.

Need help? Contact our support team