Skip to content
API

Unturned inventory

Unturned inventory API with item values

Request game=unturned to normalize public Unturned inventory items. Steam Market prices are refreshed in resumable bounded sweeps and never replace an item with a fake zero.

GET /v1/inventory?game=unturnedBearer authentication

Updated

curlWOK API
curl --fail-with-body \
  -H "Authorization: Bearer $WOK_API_KEY" \
  "https://woksteamapi.com/v1/inventory?steam_id=76561198090744629&game=unturned&top=10"
game=unturneddocumented game key
Groupedmarket items and counts
USD valuesmatched Steam prices
Resumablebounded nightly sweep

Keep an Unturned item when its price is unavailable

Unturned uses Steam AppID 304930, context 2. Set game=unturned&top=0 to receive all grouped public items, including those without a saved market price.

Read status first: a private inventory does not prove the player owns no items. For status=ok, retain every row, even when items[].pricemedian=null, and report unpriced as incomplete valuation.

Copy a real items[].markethashname into MARKET_HASH_NAME and request the saved quote. A 404 means no catalog match now; keep the item and its price unknown. An old steam_market observation is not automatically nulled, so compare updated_at with your own age policy.

When catalog coverage changes, a normal fresh cache hit reapplies local prices without a new Steam scan. To require cache-only repricing, use refresh_prices=1 while a compatible snapshot exists; inventory_cache_miss means a separate normal inventory request is needed.

Check a saved Unturned quoteWOK API
curl --fail-with-body \
  -H "Authorization: Bearer $WOK_API_KEY" \
  --get "https://woksteamapi.com/v1/price" \
  --data-urlencode "game=unturned" \
  --data-urlencode "name=$MARKET_HASH_NAME"

A market-name quote and an inventory snapshot have different timestamps. Show the selected quote's source and updated_at separately from meta.cache_age; the quote endpoint does not force a live Steam Market fetch.

Cache and repricing workflowSource timestampsUnturned response fields

Quickstart

Use WOK from a trusted server. Keep the API key outside browser bundles and public repositories.

curlWOK API
curl --fail-with-body \
  -H "Authorization: Bearer $WOK_API_KEY" \
  "https://woksteamapi.com/v1/inventory?steam_id=76561198090744629&game=unturned&top=10"
JavaScript (Node.js)WOK API
// Node.js: keep the API key on your server.
const url = new URL("https://woksteamapi.com/v1/inventory");
url.search = new URLSearchParams({
  steam_id: "76561198090744629",
  game: "unturned",
  top: "10"
});
const response = await fetch(url, {
  headers: { Authorization: `Bearer ${process.env.WOK_API_KEY}` }
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
const inventory = await response.json();
PythonWOK API
import os
import requests

response = requests.get(
    "https://woksteamapi.com/v1/inventory",
    headers={"Authorization": f"Bearer {os.environ['WOK_API_KEY']}"},
    params={
        "steam_id": "76561198090744629",
        "game": "unturned",
        "top": 10,
    },
    timeout=30,
)
response.raise_for_status()
inventory = response.json()

Response example

The values below illustrate the response shape. Field names and types match the public contract. The market name illustrates a real Steam listing, but the sample price, timestamp, count and totals are fictional. Copy items[].markethashname from the actual inventory before requesting a quote.

JSON

application/json
{
  "steamid": "76561198090744629",
  "game": "unturned",
  "status": "ok",
  "total": 24.68,
  "items_total": 2,
  "sellable": 2,
  "untradable": 0,
  "untradable_value": 0.0,
  "tradelocked": 0,
  "tradelocked_value": 0.0,
  "unpriced": 0,
  "items": [
    {
      "markethashname": "Purple Mystery Box",
      "count": 2,
      "game": "unturned",
      "tradable": 1,
      "marketable": 1,
      "pricemedian": 12.34,
      "prices": {
        "steam_market": 12.34
      },
      "pricesource": "steam_market",
      "priceupdatedat": 1787572800.0
    }
  ],
  "meta": {
    "cached": true,
    "shared": false,
    "lane": "cache",
    "saved": false,
    "ms": 0,
    "bytes": 0,
    "paid_bytes": 0,
    "upstream_attempts": 0,
    "detail": "",
    "cache_age": 42,
    "cache_ttl": 1800,
    "price_source": "steam"
  }
}

Response schema

Stable fields for typed clients, storage and error handling.

Unturned inventory API with item values response schema
FieldTypeMeaning
steamidstringCanonical 17-digit SteamID64.
gamestringDocumented key: cs2, rust, tf2, dota2, pubg, sandbox, unturned or payday2. Numeric Steam appids are also accepted and returned as app<appid> without catalog pricing.
statusstringok, empty, private, notfound, limited or error.
totalnumberPriced sellable inventory total in USD.
items_totalintegerNumber of item instances before top truncation.
sellableintegerTradable and marketable item instances, including unpriced ones; total sums matched values.
untradableintegerItem instances excluded from sellable value.
untradable_valuenumberValue of excluded untradable items in USD.
tradelockedintegerItem instances currently trade locked.
tradelocked_valuenumberValue of trade-locked items in USD.
unpricedintegerInstances without a usable price.
items[]arrayItems with market names, count, trade state, prices and optional inspect links.
items[].markethashnamestringCanonical price-catalog market hash name.
items[].marketnamestringSteam market display name when supplied.
items[].typestringSteam-supplied item type text; not a WOK-normalized category.
items[].countintegerGrouped item instance count.
items[].tradableintegerSteam tradability flag, 0 or 1.
items[].marketableintegerSteam marketability flag, 0 or 1.
items[].tradelockedbooleanWhether the grouped item is trade locked.
items[].tradelockuntilnumber|nullUnix expiry when a trade lock is known.
items[].pricemediannumber|nullSelected source median price in USD.
items[].pricesourcestringSelected catalog source; empty when the item is unpriced.
items[].priceupdatedatnumber|nullSelected source observation time, separate from inventory cache age.
items[].pricesobjectPer-source USD prices.
items[].inspect_linksarrayOptional CS2 inspect actions.
metaobjectCache age/TTL, cached/shared flags, timing, bytes, lane and upstream-attempt metadata.
meta.cachedbooleanWhether the inventory snapshot was reused.
meta.sharedbooleanWhether this request joined an in-flight singleflight fetch.
meta.cache_ageintegerSnapshot age in seconds.
meta.cache_ttlintegerApplied freshness window in seconds.

Limits and error behavior

Rules clients should handle explicitly in production.

The Steam inventory must be public. Private, missing and empty inventories are distinct statuses, not successful empty data.

top accepts 0 through 100. top=0 returns every item row; items_total still describes the complete inventory when a top limit is used.

Prices are USD. An item can be valid while pricemedian is null; use unpriced instead of treating missing prices as zero-value evidence.

A partial or malformed Steam inventory is not saved as a successful snapshot. On GET /v1/inventory, validation/auth failures use HTTP 400/401/402/404/422/429; Steam outcomes private, notfound, limited and error are returned with HTTP 200 in response.status. The compatibility GET /steam/api/inventory maps them to 403/404/429/502 (empty to 410).

Unturned catalog liquidity varies by item. A missing or stale market observation needs different handling: missing prices remain unpriced, while an old saved price may still be returned. Check priceupdatedat against your own age limit.

Cache and freshness semantics

How to tell whether data was reused, shared or refreshed.

Successful inventory snapshots use a 1,800-second default TTL. Negative defaults are 21,600 seconds for empty, 3,600 seconds for private and 600 seconds for not found.

For authenticated inventory responses that reach validation/result handling, read X-Wok-Cache-Age and X-Wok-Cache-TTL when present; authentication and quota errors may omit them.

Identical concurrent misses are coalesced. A waiter receives X-Wok-Singleflight: 1 and does not start another Steam inventory fetch.

Use refresh_prices=1 or POST /v1/inventory/refresh-prices only with an active compatible OK/EMPTY snapshot. Repricing never fetches Steam or resets inventory age/TTL; 404 inventory_cache_miss means run a normal inventory scan. refresh_prices=1 cannot be combined with no_cache=1; prices_updated_at identifies the repricing operation.

Frequently asked questions

Direct answers about access, freshness and result semantics.

Which game value selects Unturned?

Use game=unturned with GET /v1/inventory.

How are low-liquidity items represented?

An item without a saved price remains in the response and contributes to unpriced. A saved quote can be old without becoming null automatically; inspect priceupdatedat.