TRADERUST
Sign in with Steam
traderust API · v1.0

Build on the traderust order book

Everything the site does, as JSON: read prices and order books, quote and execute buys, sells and swaps, place and cancel orders, and get every change pushed over a WebSocket the moment it happens.

Base URLhttps://traderust.com
FormatJSON in, JSON out
AuthAuthorization: Bearer trk_…
Machine-readable/api/openapi.json

Market data is public. Anything about your account needs an API key. The API is the same one the site itself uses, so it always has every feature the site has.

API keys

Send your key in the Authorization header on every request:

curl -H "Authorization: Bearer trk_your_key" https://traderust.com/api/me
ScopeAllows
readEvery GET endpoint, POST /api/quote, and your private WebSocket pushes. Every key has it.
tradeInstant trades, placing and cancelling orders, Steam deposits and offer cancels, crypto deposits.
Keys can never move value off traderust. Withdrawing skins to Steam, cashing out crypto, changing your Steam trade URL and managing keys all need you signed in on the site (session_only). A leaked key can trade, but it can't take anything out. Revoke a key here and it stops working immediately.

Your keys

Sign in with Steam to create API keys.

Money & prices

All money is an integer number of mills: 1 mill = $0.001, so 960 is $0.960 and 50000 is $50. No floats anywhere - send mills, get mills.

Every skin has one order book, and trading is free: no fees on buying, selling, swapping or orders. A trade at $0.941 moves exactly $0.941. ask / bid are the best prices on the book; buy_shown / sell_shown and a level's shown are what you pay or get trading instantly - today always the same number.

Moving skins to and from Steam is free too. The only fee is on crypto cash-outs: 2%, taken out of the amount (cash out $50 → receive $49 in crypto) and charged only once the payout is actually sent. Cash-outs need you signed in on the site - they're never available to API keys.

Exact pricing

You never get less than you were quoted. The flow is always quote → trade:

  1. POST /api/quote with your basket. It returns net: the change to your balance (negative = you pay).
  2. POST /api/trade with the same basket and min_net_mills = that net.
  3. If the book moved against you, nothing trades and you get price_changed - quote again. If it moved in your favour you get the better price.

Quotes only count buyers who can pay at that moment, and a multi-skin quote shares each buyer's balance across every line - so fillable: true means the whole basket fills unless the book changes before you trade.

Errors

Every error has the same shape, with a stable code to branch on and a human error to show:

{"error": "Prices changed since you looked. Nothing was traded - check the new prices and press again.", "code": "price_changed"}
codeHTTPMeaning
auth_required401No key and not signed in.
bad_key401The key is wrong or was revoked.
scope403The key lacks the scope this call needs (trade).
session_only403Keys can't do this (withdrawals, trade URL, keys) - sign in on the site.
rate_limited429Too many requests for this key this minute.
invalid422The request body or parameters are malformed - error says which field.
price_changed400/api/trade: the book moved against your min_net_mills. Nothing traded - quote again.
would_cross400/api/orders: your price would trade instantly. Use a better price or /api/trade.
error400Anything else (not enough balance or skins, unknown item, order not found...). error explains.
http_404404No such skin / order / offer.

Rate limits

Per key, per minute: 600 read requests and 120 trade requests. Over the limit you get 429 rate_limited until the minute rolls over. Don't poll - subscribe and the changes come to you.

Market data

Public - no key needed. Prices are live order-book prices.

GET/api/markets public

List skins with their best prices

Search and page through every skin. With for_sale=1 you get only skins someone is selling right now, filtered and sorted by the best sell order - the same list as the trade page's right-hand side.

QueryType
qstringName contains (case-insensitive).
catstringCategory, e.g. clothing, weapon, deployable, resource.
sortstringColumn: name · buy · sell · gap · for_sale · wanted · sold (default). Older names price / cheap / volume still work.
dirstringdesc (default; names default to asc) or asc. Skins with no price always sort last.
<col>_min / <col>_maxnumberFilter any column: buy_min, buy_max, sell_min, sell_max (mills), gap_min, gap_max (percent), for_sale_min/max, wanted_min/max (skins), sold_min/max (sold last week).
only_book0|11 (default): only skins with at least one open order.
for_sale0|11: only skins with open sell orders; price sorts use the best ask.
limitint1-200, default 60.
offsetintFor paging.
Response
{
  "total": 5565,
  "items": [
    {
      "id": 2457,
      "name": "Hellforged Vest",
      "icon": "https://files.facepunch.com/rust/icons/inventory/rust/70010_small.png",
      "category": "clothing",
      "fair": 905,
      "weekly_sales": 79,
      "ask": 941,
      "ask_qty": 23,
      "bid": 891,
      "bid_qty": 19,
      "buy_shown": 941,
      "sell_shown": 891
    }
  ]
}
GET/api/items/{item_id} public

One skin: prices, top of book, recent trades

Signed in (or with a key), mine and held are filled in with your open orders on this skin and how many you hold.

Response
{
  "item": {
    "id": 2457,
    "name": "Hellforged Vest",
    "icon": "https://files.facepunch.com/rust/icons/inventory/rust/70010_small.png",
    "category": "clothing",
    "fair": 905,
    "weekly_sales": 79,
    "ask": 941,
    "ask_qty": 23,
    "bid": 891,
    "bid_qty": 19,
    "buy_shown": 941,
    "sell_shown": 891
  },
  "book": {
    "bids": [
      {
        "price": 891,
        "qty": 1,
        "orders": 1,
        "shown": 891
      },
      {
        "price": 868,
        "qty": 2,
        "orders": 1,
        "shown": 868
      }
    ],
    "asks": [
      {
        "price": 941,
        "qty": 5,
        "orders": 1,
        "shown": 941
      },
      {
        "price": 968,
        "qty": 2,
        "orders": 1,
        "shown": 968
      }
    ]
  },
  "trades": [
    {
      "price": 941,
      "qty": 1,
      "side": "buy",
      "at": "2026-10-27T06:11:17.570235"
    }
  ],
  "volume_24h": 1,
  "ref": {
    "cash_ask_low": 890,
    "cash_bid_high": 870,
    "steam_avg7_net": 1100
  },
  "mine": [],
  "held": {
    "available": 0,
    "locked": 0
  }
}
GET/api/items/{item_id}/depth public

Full order book (40 levels a side)

price is the price per skin; shown is what you pay (asks) or get (bids) trading instantly - the same, as there are no trading fees. Only orders whose owners can currently pay for them are counted.

Response
{
  "bids": [
    {
      "price": 891,
      "qty": 1,
      "orders": 1,
      "shown": 891
    },
    {
      "price": 868,
      "qty": 2,
      "orders": 1,
      "shown": 868
    }
  ],
  "asks": [
    {
      "price": 941,
      "qty": 5,
      "orders": 1,
      "shown": 941
    },
    {
      "price": 968,
      "qty": 2,
      "orders": 1,
      "shown": 968
    }
  ]
}
GET/api/items/{item_id}/chart public

Price history

steam: [time, Steam median sale price, Steam volume] - Steam prices include Steam's ~15% fee. band: [time, best bid, best ask] snapshots of this market. trades: [time, price, qty, side of the instant trader].

QueryType
rangestring1w · 1m (default) · 3m · 1y · all
Response
{
  "range": "1w",
  "steam": [
    [
      "2026-10-20T07:00:00",
      1210,
      1
    ]
  ],
  "band": [
    [
      "2026-10-27T06:00:00",
      891,
      941
    ]
  ],
  "trades": [
    [
      "2026-10-27T06:11:17",
      941,
      1,
      "buy"
    ]
  ],
  "fair": 905
}
GET/api/items/{item_id}/stats public

24h and 7-day statistics

Response
{
  "last": 941,
  "prev_24h": 930,
  "volume_24h": 12,
  "value_24h": 11208,
  "steam_avg_7d": 1267,
  "steam_sold_7d": 73
}
GET/api/prices public

Every skin's prices in one call (for price sites)

Best ask (lowest sell order) and bid (highest buy order its owner can pay), the quantity behind each, and 7 / 30-day sales (units and median trade price) for every skin with orders or recent trades. Rebuilt every minute; cache it for at least 30 seconds. url links straight to the skin's page by market name.

Response
{
  "updated_at": "2026-10-27T16:40:00Z",
  "currency": "USD",
  "unit": "mills",
  "trading_fee_percent": 0,
  "cashout_fee_percent": 2.0,
  "items": [
    {
      "market_hash_name": "Hellforged Vest",
      "ask": 941,
      "ask_qty": 23,
      "bid": 891,
      "bid_qty": 19,
      "sold_7d": 12,
      "median_7d": 930,
      "sold_30d": 40,
      "median_30d": 925,
      "url": "https://traderust.com/i/Hellforged%20Vest"
    }
  ]
}
GET/api/stats public

Site stats - everything, public

Volume (24h / 7 days / all time), users, open orders and their value, skins and cash held for users, crypto cash-ins and cash-outs, the site's fee revenue and cash-outs waiting to be paid - aggregates only, never anyone's individual data. Recalculated every minute; 503 warming for the first minute after a restart. Live: WebSocket op stats.

Response
{
  "updated_at": "2026-10-27T10:32:42",
  "volume": {
    "24h": {
      "trades": 256,
      "value": 113397,
      "skins": 433
    },
    "7d": {
      "\u2026": "\u2026"
    },
    "all": {
      "\u2026": "\u2026"
    }
  },
  "users": {
    "total": 20,
    "new_24h": 3,
    "traded_24h": 14
  },
  "orders": {
    "open": 55689,
    "buy": 27858,
    "buy_value": 624902423,
    "sell": 27831,
    "sell_value": 739337319,
    "skins_for_sale": 5565,
    "skins_with_orders": 5565
  },
  "held": {
    "skins": 152810,
    "value": 656963540,
    "cash": 125618074
  },
  "money": {
    "24h": {
      "crypto_in": {
        "count": 6,
        "value": 500000
      },
      "crypto_out": {
        "count": 1,
        "value": 12098
      },
      "fees": 247,
      "skins_in": 247,
      "skins_out": 27
    },
    "7d": {
      "\u2026": "\u2026"
    },
    "all": {
      "\u2026": "\u2026"
    }
  },
  "cashouts_pending": {
    "count": 0,
    "value": 0,
    "needs_review": 0
  },
  "daily": [
    {
      "day": "2026-10-27",
      "trades": 256,
      "value": 113397
    }
  ],
  "top_7d": [
    {
      "item_id": 2457,
      "name": "Hellforged Vest",
      "icon": "https://\u2026",
      "qty": 12,
      "value": 11292,
      "trades": 9,
      "last": 941
    }
  ],
  "recent": [
    {
      "item_id": 2457,
      "name": "Hellforged Vest",
      "icon": "https://\u2026",
      "qty": 1,
      "price": 938,
      "side": "buy",
      "at": "2026-10-27T06:31:06"
    }
  ]
}

Your account

Needs a key (read scope) or a signed-in session.

GET/api/me read scope

Your balance and skins

usd.available is cash you can trade; withdrawable is what can be cashed out right now. buy_orders is the total of your open buy orders - they reserve nothing and are paid from available when they fill. items lists every skin you hold on traderust with its live prices.

Response
{
  "user": {
    "id": 21,
    "name": "alice",
    "avatar": null,
    "steamid": "76561198000000000",
    "trade_url": "https://steamcommunity.com/tradeoffer/new/?partner=\u2026"
  },
  "usd": {
    "available": 50000,
    "locked": 0,
    "withdrawable": 50000,
    "held": 0,
    "buy_orders": 2550,
    "buying_power": null,
    "multiple": null
  },
  "items": [
    {
      "id": 2457,
      "name": "Hellforged Vest",
      "icon": "https://files.facepunch.com/rust/icons/inventory/rust/70010_small.png",
      "category": "clothing",
      "fair": 905,
      "weekly_sales": 79,
      "ask": 941,
      "ask_qty": 23,
      "bid": 891,
      "bid_qty": 19,
      "buy_shown": 941,
      "sell_shown": 891,
      "available": 1,
      "locked": 0
    }
  ]
}
GET/api/orders read scope

Your orders

price is per skin - exactly what you pay (buy) or get (sell) for each one that fills.

QueryType
statusstringopen (default) or closed (cancelled - reason says why)
Response
{
  "orders": [
    {
      "id": 56967,
      "item_id": 2457,
      "name": "Hellforged Vest",
      "icon": "https://files.facepunch.com/\u2026",
      "side": "buy",
      "price": 850,
      "qty": 3,
      "filled": 0,
      "status": "open",
      "reason": null,
      "source": "limit",
      "created_at": "2026-10-27T06:11:17.642802"
    }
  ]
}
GET/api/history read scope

Your fills and instant trades

trades: every fill you were part of (last 100). role is order (your resting order filled) or instant; cash is what it did to your balance. executions: your instant trades / swaps as a whole.

Response
{
  "trades": [
    {
      "id": 268,
      "name": "Hellforged Vest",
      "item_id": 2457,
      "side": "buy",
      "qty": 1,
      "price": 941,
      "role": "instant",
      "cash": -941,
      "at": "2026-10-27T06:11:17.570235"
    }
  ],
  "executions": [
    {
      "id": 97,
      "kind": "buy",
      "net": -941,
      "lines": [
        {
          "item_id": 2457,
          "name": "Hellforged Vest",
          "side": "buy",
          "qty": 1,
          "total": 941,
          "avg_shown": 941
        }
      ],
      "at": "2026-10-27T06:11:17.556717"
    }
  ]
}
GET/api/history/trades read scope

Trade history (paged)

Every fill you were part of, newest first - same shape as /api/history trades, plus icon. more says whether another page exists. The first page (no before) also has totals.

QueryType
beforeintegerReturn fills older than this id (the last id of the previous page).
sidestringbuy or sell (default both)
limitinteger1-200, default 50
Response
{
  "trades": [
    {
      "id": 268,
      "name": "Hellforged Vest",
      "icon": "https://\u2026",
      "item_id": 2457,
      "side": "buy",
      "qty": 1,
      "price": 941,
      "role": "instant",
      "cash": -941,
      "at": "2026-10-27T06:11:17.570235"
    }
  ],
  "more": false,
  "totals": {
    "buys": 1,
    "bought_qty": 1,
    "bought_usd": 941,
    "sells": 0,
    "sold_qty": 0,
    "sold_usd": 0
  }
}
GET/api/history/executions read scope

Instant trades and swaps (paged)

Each instant buy, sell or swap as a whole. net is the change to your balance.

QueryType
beforeintegerReturn executions older than this id.
limitinteger1-100, default 30
Response
{
  "executions": [
    {
      "id": 97,
      "kind": "buy",
      "net": -941,
      "lines": [],
      "at": "2026-10-27T06:11:17.556717"
    }
  ],
  "more": false
}
GET/api/history/transfers read scope

Deposits and withdrawals (paged)

Crypto deposits and cash-outs, and Steam skin deposits and withdrawals, newest first. type is crypto or skins: crypto rows are /api/crypto rows, skins rows are /api/steam/offers rows. The first page also has totals (crypto_out and fees count finished cash-outs; crypto_pending is cash-outs still on their way; skins count completed trades).

QueryType
kindstringall (default) · crypto · skins
directionstringdeposit or withdraw (default both)
beforestringISO timestamp: rows created before it (the last row's created_at).
limitinteger1-100, default 40
Response
{
  "rows": [
    {
      "type": "crypto",
      "id": 12,
      "direction": "withdraw",
      "coin": "usdttrc20",
      "usd": 50000,
      "credited": null,
      "fee": 1000,
      "status": "finished",
      "address": "T\u2026",
      "created_at": "2026-10-27T06:11:17",
      "cancellable": false
    }
  ],
  "more": false,
  "totals": {
    "crypto_in": 100000,
    "crypto_out": 50000,
    "fees": 1000,
    "crypto_pending": 0,
    "skins_in": 4,
    "skins_out": 1
  }
}
GET/api/ledger read scope

Every balance change

The append-only ledger behind your balances. d_available / d_locked are the change to each.

QueryType
beforeintegerReturn rows older than this id.
limitinteger1-300, default 150
Response
{
  "rows": [
    {
      "id": 41923,
      "asset": "Hellforged Vest",
      "is_usd": false,
      "d_available": 1,
      "d_locked": 0,
      "kind": "fill_receive",
      "at": "2026-10-27T06:11:17.577807"
    }
  ],
  "more": false
}

Trading

Quotes need read; everything that changes your balances needs the trade scope.

POST/api/quote read scope

Price a buy, sell or swap

What you'd get or pay right now for any basket. Nothing is reserved. net is the change to your balance: negative = you pay. fillable is false if the book can't fill every line in full. For a live quote that updates by itself, use the WebSocket quote op.

Request body - Each line is [item_id, qty]. give: skins on traderust. steam_give: skins still in your Steam inventory. get: skins to buy.
{
  "give": [
    [
      1092,
      1
    ]
  ],
  "steam_give": [],
  "get": [
    [
      2457,
      2
    ]
  ]
}
Response
{
  "lines": [
    {
      "item_id": 2457,
      "name": "Hellforged Vest",
      "side": "buy",
      "source": "market",
      "qty": 2,
      "fillable": 2,
      "total": 1882,
      "unit_shown": 941
    }
  ],
  "net": -1882,
  "fillable": true,
  "kind": "buy",
  "cash_available": 50000,
  "withdrawable": 50000,
  "pending": false
}
POST/api/trade trade scope

Buy, sell or swap instantly

Fill-or-kill against the book. min_net_mills is the quote's net you accept as the worst case - pass the quote's net exactly. If prices moved against you nothing trades and you get price_changed; if they moved in your favour you get the better price. With steam_give the trade waits for your Steam deposit (pending: true) and then runs only at min_net_mills or better.

Request body - Each line is [item_id, qty].
{
  "give": [],
  "steam_give": [],
  "get": [
    [
      2457,
      1
    ]
  ],
  "min_net_mills": -941
}
Response
{
  "pending": false,
  "execution_id": 97,
  "net": -941,
  "lines": [
    {
      "item_id": 2457,
      "name": "Hellforged Vest",
      "side": "buy",
      "qty": 1,
      "total": 941,
      "avg_shown": 941
    }
  ]
}
POST/api/orders trade scope

Place a buy or sell order

Post-only: an order that would trade instantly is rejected with would_cross - use /api/trade for that. price_mills is per skin, 1-100,000,000; qty 1-10,000. Sell orders set the skins aside. Buy orders set nothing aside - they're paid from your balance when they fill, and an order your balance can't cover at that moment is cancelled (reason: balance).

Request body
{
  "item_id": 2457,
  "side": "buy",
  "price_mills": 850,
  "qty": 3
}
Response
{
  "order": {
    "id": 56967,
    "item_id": 2457,
    "name": "Hellforged Vest",
    "icon": "https://files.facepunch.com/\u2026",
    "side": "buy",
    "price": 850,
    "qty": 3,
    "filled": 0,
    "status": "open",
    "reason": null,
    "source": "limit",
    "created_at": "2026-10-27T06:11:17.642802"
  }
}
DELETE/api/orders/{order_id} trade scope

Cancel an order

Anything it set aside comes straight back.

Response
{
  "ok": true
}

Steam & crypto

Moving skins and money in. Withdrawals are never available to API keys.

POST/api/steam/deposit trade scope

Deposit skins from Steam

Sends you a Steam trade offer for these skins (from your Steam inventory). They land in your traderust inventory when you accept it on Steam. Needs your trade URL set on the site.

Request body - Each line is [item_id, qty].
{
  "lines": [
    [
      2457,
      1
    ]
  ]
}
Response
{
  "offer_id": 108
}
GET/api/steam/offers read scope

Your Steam trade offers

status: pending · sent · escrow · cancelling · completed · declined · cancelled · expired · failed. Balances change only on the final state Steam reports.

Response
{
  "offers": [
    {
      "id": 108,
      "direction": "deposit",
      "status": "sent",
      "reason": null,
      "steam_offer_id": "7740012345",
      "lines": [
        {
          "item_id": 2457,
          "name": "Hellforged Vest",
          "icon": "https://files.facepunch.com/\u2026",
          "qty": 1
        }
      ],
      "cancellable": true,
      "expires_at": "2026-10-27T06:21:17",
      "created_at": "2026-10-27T06:11:17",
      "pending_trade": null
    }
  ]
}
POST/api/steam/offers/{offer_id}/cancel trade scope

Cancel a Steam trade offer

If Steam reports it was already accepted, the accept wins and the trade completes.

Response
{
  "status": "cancelled",
  "reason": "cancelled by you"
}
POST/api/crypto/address trade scope

Your permanent crypto deposit address

One address per coin, yours permanently: send any amount above min_usd, any time, as often as you like - each transfer is credited by itself, for what actually arrives, once the network confirms it. extra_id is a memo/tag you must include when set. Created the first time you ask for that coin.

Request body
{
  "coin": "usdttrc20"
}
Response
{
  "coin": "usdttrc20",
  "address": "TARNr8\u2026",
  "extra_id": null,
  "min_usd": 13.42,
  "simulated": false
}
POST/api/crypto/deposit trade scope

Add money with crypto

Returns the address and exact amount to send. Your balance is credited when the payment confirms.

Request body
{
  "usd_mills": 50000,
  "coin": "btc"
}
Response
{
  "id": 1,
  "status": "waiting",
  "address": "bc1q\u2026",
  "extra_id": null,
  "amount": "0.00071",
  "coin": "btc",
  "credited": 0
}
GET/api/crypto read scope

Your crypto deposits and cash-outs

Response
{
  "rows": [
    {
      "id": 1,
      "direction": "deposit",
      "coin": "btc",
      "usd": 50000,
      "credited": 50000,
      "status": "finished",
      "address": "bc1q\u2026",
      "created_at": "2026-10-27T06:11:06",
      "cancellable": false
    }
  ]
}

WebSocket - live updates

Connect to wss://traderust.com/live. Everything is JSON. Order books, your balances and live quotes are pushed within ~100ms of every change (one push per burst), so there's nothing to poll. Trading itself stays on the REST endpoints above.

You send

{"op": "auth", "key": "trk_…"}Sign in with a key (or send Authorization: Bearer on the upgrade request). Without it you still get public data.
{"op": "sub", "items": [2457, 1092]}Live order book, best prices and trades for these skins (up to 600).
{"op": "unsub", "items": [1092]}Stop.
{"op": "stats"}The public site stats now (same shape as /api/stats), then again every time they're recalculated (every minute).
{"op": "quote", "id": 7, "give": [], "steam_give": [], "get": [[2457, 2]]}A live quote: replied to now, and pushed again every time a skin in it changes - until your next quote op. id is yours; it comes back on every push so you can drop stale ones. Max 50 quote ops per 10 seconds.

You receive

{"type": "hello", "user": {"id": 21} | null}On connect.
{"type": "auth", "user": {"id": 21}}Your auth op worked.
{"type": "item", "item": {…}, "book": {…}, "trades": […], "volume_24h": 12}A subscribed skin changed (same shapes as /api/items/{id}). Bursts are coalesced to one push per ~100ms.
{"type": "me", "usd": {"available": …, "locked": …, "withdrawable": …, "held": …, "buy_orders": …}}Your balances changed (a fill, a deposit, a cancel...). Private to your connections.
{"type": "quote", "id": 7, "quote": {…}}Your live quote (same shape as /api/quote).
{"type": "refresh"}Something changed in bulk - refetch what you show.
{"type": "stats", "stats": {…}}Fresh site stats (after op stats).
{"type": "error", "code": "bad_key" | "rate_limited", "error": "…"}The op was refused.

If the connection drops, reconnect, then re-send auth, your subscriptions and your live quote. Pushes carry the full current state, never a diff, so a missed push is fixed by the next one.

Examples

# what's for sale, cheapest first
curl "https://traderust.com/api/markets?for_sale=1&sort=cheap&limit=5"

# quote buying 2 of skin 2457, then buy at exactly that price
curl -X POST https://traderust.com/api/quote -H "Authorization: Bearer $TR_KEY" -H "Content-Type: application/json" \
     -d '{"get": [[2457, 2]]}'
curl -X POST https://traderust.com/api/trade -H "Authorization: Bearer $TR_KEY" -H "Content-Type: application/json" \
     -d '{"get": [[2457, 2]], "min_net_mills": -1882}'

# rest a buy order at $0.850 each - it fills later, at exactly that price
curl -X POST https://traderust.com/api/orders -H "Authorization: Bearer $TR_KEY" -H "Content-Type: application/json" \
     -d '{"item_id": 2457, "side": "buy", "price_mills": 850, "qty": 3}'