Developer reference
Avan Market API
Quick start
Buying a skin for your customer takes four steps:
- Get an API key in your account on avan.market and top up your balance.
-
Find the skin you need via search or the price list — you need its
id. -
Send a buy request with the recipient's trade link parameters and your own
custom_id. - Track the status via WebSockets until it becomes final.
curl https://api.avan.market/v1/user/balance \
-H "Authorization: Bearer $AVAN_API_KEY"
curl -X POST https://api.avan.market/v1/market/buy \
-H "Authorization: Bearer $AVAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"id": "8f3a1d6e-b204-4c59-a6e7-1b9d5c0f7e23",
"partner": "358881436",
"token": "l6LFC3R8",
"max_price": 3.60,
"custom_id": "order-10457"
}'
Base URL
All methods are called relative to a single base URL:
https://api.avan.market/v1/
Data format
-
Requests and responses are JSON in UTF-8.
POSTrequests need the headerContent-Type: application/json. - All prices and amounts are in US dollars (USD).
-
Dates are in ISO 8601, UTC. Time filters and the
last_updatefield use UNIX time in seconds. - Arrays in the query string are passed by repeating the parameter:
ids[]=a&ids[]=b. - New fields may appear in responses — this is not a version change. Do not rely on the set of fields being closed.
Games
In parameters and responses a game is identified by its Steam App ID; in the price list URL, by a short word.
| Game | App ID | In the price list URL |
|---|---|---|
| Counter-Strike 2 | 730 | cs |
| Dota 2 | 570 | dota |
| Rust | 252490 | rust |
| Team Fortress 2 | 440 | tf |
Authentication
Every request must include your API key. Pass it in the Authorization header using the Bearer scheme:
Authorization: Bearer [API_KEY]
- The key is created in your account on avan.market, in the “API Key” section, and shown only once — save it right away.
- The section unlocks once you have spent $10 or more on the market in total. This amount is not a connection fee and is not charged.
- The key gives access to your balance. Keep it on your server only and never ship it to a browser or a mobile app.
- If the key is exposed, reissue it in your account — the old one stops working within 30 seconds.
What the server returns when the key is missing or invalid
Response status: 401
{
"code": "unauthorized",
"message": "Missing or invalid API key."
}
Rate limits
v1/market/buy)Limits are counted per API key, not per IP address. The counters are independent: buy requests do not consume the shared limit, and other methods do not consume the buy limit.
The counter resets 60 seconds after the first request. When the limit is exhausted, wait up to a minute and send the request again.
In addition, an account can have at most 10 buy requests in progress at the same time. The eleventh gets 429 with the code too_many_concurrent_purchases — retry it once one of the earlier requests completes.
What the server returns when the limit is exceeded
Response status: 429
{
"code": "rate_limited",
"message": "Request limit exceeded. Retry in a minute."
}
Errors
A successful response has status 200 (a price list may return 304, see price lists). Any other status means an error, and the response body contains a message field with a description.
| Status | When it occurs | What to do |
|---|---|---|
401 | The key is missing, invalid or revoked | Check the header Authorization |
403 | The account is blocked | Contact support |
404 | The method or object was not found | Check the URL and the identifier |
409 | The request is valid but cannot be completed: the skin is already sold, the balance is too low | Check the field code — see buy errors |
422 | The parameters failed validation | The errors object lists the messages for each field |
429 | The rate limit is exceeded | Wait up to a minute and send the request again |
500, 502, 503, 504 | A failure on the Avan Market side | Retry later. A purchase — only after checking by custom_id, see tips |
Validation error — 422
{
"message": "The partner field is required. (and 1 more error)",
"errors": {
"partner": [
"The partner field is required."
],
"token": [
"The token field is required."
]
}
}
The request cannot be completed — 409
{
"code": "skin_unavailable",
"message": "The skin is already sold or reserved."
}
The code field is a short, stable error name. Check this value in your code: the text in
message may change.
Pagination
Long lists are returned in parts. The API has two kinds of pagination — each method's description says which one it uses.
Page-based — purchase history
Select the page with the page query parameter. For example,
GET /v1/market/history?page=4:
{
"data": [
...
],
"meta": {
"current_page": 4,
"last_page": 6,
"per_page": 200,
"total": 1150
}
}
The meta block describes the whole result set: in this example the account has 1,150 purchases at 200 per page, which makes 6 pages. The number of the returned page comes back in
meta.current_page — an easy way to confirm you got the page you asked for.
Cursor-based — skin search
The catalog changes every second, so search has no page numbers and no total count. Instead, the response carries the cursor meta.next_page:
{
"data": [
...
],
"meta": {
"per_page": 200,
"next_page": "eyJwIjoiZDJjNWI4ZjEtM2E0Ni00ZTcwLTliMWMtN2U0ZjBhNmQ4YzkyIn0"
}
}
To get the next part, pass this value in the parameter next_page:
GET /v1/market/search?game=730&next_page=eyJwIjoi...
- When
meta.next_pageisnull, there are no more results. - A cursor only works with the same filters it was obtained with.
- A cursor is an opaque string: do not parse it or build it yourself.
How a purchase works
Response 200 to a buy request means the purchase is created and the money is charged, but the skin has not been delivered yet. The purchase then goes through several stages, each of which changes its
status.
| Stage | What happens | Status |
|---|---|---|
| 1. Purchase accepted | The skin is reserved for you and its price is charged to your balance. The purchase is reviewed on the Avan Market side | "0" |
| 2. Trade sent | A Steam trade offer has been sent to the recipient; waiting for their decision | "2" |
| 3a. Skin delivered | The recipient accepted the trade. The purchase is complete | "3" |
| 3b. Delivery failed | The purchase did not pass the review, or the trade was declined, expired, canceled or never created. The money is refunded to your balance unless the recipient declined the trade themselves | "6", "7", "8", "10" |
Delivery time
Not every skin can be delivered right away: some items are under a temporary Steam trade restriction. The delivery time is known in advance from the item's delivery field: 1 — the trade is sent right after the purchase is reviewed, 2 — within 12 hours. Until then the purchase stays in status
"0".
Refunds
If a purchase ends in any final status other than "3", its price is refunded to your balance. The reason is stored in return_reason, and if part of the amount was withheld — in
return_charged_commission.
| return_reason | When |
|---|---|
trade_declined | The recipient declined the trade |
trade_canceled | The trade was canceled: the recipient did not accept it in time, or the purchase did not pass the review |
trade_create_failed | The trade could not be created: private inventory, invalid link, Steam restrictions |
item_unavailable | The item turned out to be unavailable for transfer |
return_charged_commission.
What is required from the recipient
The recipient's account and trade link are not checked in advance. If the trade cannot be created — for example, because of a trade ban or a private inventory — the purchase ends with status "10", and the money is refunded to your balance.
- The Steam inventory is public and the account is not trade-restricted.
- The trade link is current: once it is regenerated in Steam, the old
tokenstops working. - The trade must be accepted before it expires, otherwise it is canceled and the purchase ends with status
"6".
Tips for buying skins
-
New listings arrive in real time only as the
skin_addedevent in WebSockets. Search and the website lag a few minutes behind, and the price list is rebuilt once a minute — use them to reconcile, not to race for fresh listings. -
Keep statuses in memory from the events of the purchases channel.
/v1/market/infois the fallback: after reconnecting and when the socket is unavailable. -
Give every purchase its own
custom_idand make retries idempotent. No response (dropped connection, timeout,5xx) — call/v1/market/info?custom_ids[]=…. An emptydatameans there is no purchase and the request can be sent again. If the purchase exists, the retry returnsduplicate_custom_idwith the purchase indata, and the skin is not charged twice. - Set a timeout of at least 35 seconds on the buy request: reserving the skin and charging can take up to 30 seconds.
-
Before buying several skins, check the prices with
/v1/market/check-basket, and in the buy request itself passmax_price— the price may change between the check and the purchase. -
If the WebSocket drops, reconnect with a growing delay (1, 2, 4, 8 seconds, but no more than 30) and after connecting reconcile the statuses of unfinished purchases with
/v1/market/info: messages sent during the outage are not replayed. -
There is no need to download a price list more often than it is updated, which is once a minute. Send
If-None-Matchso you do not download the document again if it has not changed.
Catalog and events
JSON price lists
A price list is a JSON document with full data on every item currently on sale. Each game has its own price list — pick the one you need.
-
The response is large — request it compressed with the header
Accept-Encoding: gzip. -
The price list is rebuilt once a minute. The
last_updatefield shows when it was built. -
The response carries an
ETagheader. Send its value in theIf-None-Matchheader of the next request: if the price list has not been rebuilt since, you get an empty304response. -
Right after a service restart, until the price list is built, the method returns
503— retry in a minute. - A price list is suited for a full catalog reconciliation every few minutes. To learn about new skins immediately, use WebSockets.
Response — Counter-Strike 2
{
"status": "success",
"last_update": 1773826887,
"items": [
{
"id": "9b2f6c1e-4d7a-4f0b-8a3e-5c1d2e7f9a40",
"game_id": 730,
"name": "AWP | Asiimov (Field-Tested)",
"price": 148.5,
"delivery": 1,
"asset_id": "53540956125",
"class_id": "7993037085",
"float": "0.2744107246398926",
"paint_seed": 932,
"name_tag": null,
"inspect_link": "steam://run/730//+csgo_econ_action_preview%20B9A9415A72297CB8A1B0992EBB91BF89BD810F72114CBAF916BDDBB6B1B9A9628A842CE72507FCF5801504DBB6B1B9A9029C84A50FF207FCB9B08005DBB6B1B9A9339C841D20A007FC59E06505D13A393939B5C9B17896EAA2",
"stickers": [
{
"slot": 0,
"name": "Sticker | ZywOo (Foil) | Katowice 2019",
"wear": 0,
"image": "https://community.cloudflare.steamstatic.com/economy/image/i0CoZ81Ui0m-9KwlBY1L_18myuGuq1wfhWSaZgMttyVfPaERSR0Wqmu7LAocGJai0ki7VeTHjMGgIXSA7FVwptelsxb0SBrOhI_38i1k6f2nZOo-IvPAX2bHwrtw5rFtSii2zR9-sT7Tn4mvdC7BO1chWZckROZZska4jJS5YAEgste8"
}
]
}
]
}
730 — Counter-Strike 2, 570 —
Dota 2, 252490 — Rust, 440 — Team Fortress 2
1 — immediately, 2 — within 12 hours
Response — Dota 2
{
"status": "success",
"last_update": 1773826887,
"items": [
{
"id": "3e8a1f52-7c94-4b6d-9f20-a1d4c7e85b13",
"game_id": 570,
"name": "Dragonclaw Hook",
"price": 412.3,
"delivery": 1,
"asset_id": "29384710562",
"class_id": "57949762",
"stickers": [
{
"slot": null,
"name": "Inscribed Towers Destroyed",
"wear": null,
"image": "https://cdn.steamstatic.com/apps/570/icons/econ/sockets/gem_stat.30d7935c1f0a1b9e8e28c691c2bd28f7d5f471bc.png"
}
]
}
]
}
730 — Counter-Strike 2, 570 —
Dota 2, 252490 — Rust, 440 — Team Fortress 2
1 — immediately, 2 — within 12 hours
Response — Rust
{
"status": "success",
"last_update": 1773826887,
"items": [
{
"id": "c47d9a06-2b5e-4e13-b8f7-6d0a3f91e2c5",
"game_id": 252490,
"name": "Tempered AK47",
"price": 38.5,
"delivery": 1,
"asset_id": "5193846207",
"class_id": "2143471514"
}
]
}
730 — Counter-Strike 2, 570 —
Dota 2, 252490 — Rust, 440 — Team Fortress 2
1 — immediately, 2 — within 12 hours
Response — Team Fortress 2
{
"status": "success",
"last_update": 1773826887,
"items": [
{
"id": "f15b7e3a-90c2-4a68-8d41-2e6c9b0a7d38",
"game_id": 440,
"name": "Mann Co. Supply Crate Key",
"price": 2.14,
"delivery": 1,
"asset_id": "14872039561",
"class_id": "101785959"
}
]
}
730 — Counter-Strike 2, 570 —
Dota 2, 252490 — Rust, 440 — Team Fortress 2
1 — immediately, 2 — within 12 hours
WebSockets
Over a WebSocket the server reports changes itself — faster than polling the methods, and it does not consume your rate limit.
Connecting
wss://socket.avan.market/api?token=[TOKEN]
-
Get a connection token with
/v1/user/get-ws-tokenand pass it in the parametertoken. The API key itself is never sent over the WebSocket. - Messages are exchanged as JSON. No special library is needed — any WebSocket client will do.
-
A token is valid for a limited time. When it expires, the server closes the connection with code
4002— request a new token and reconnect. - You can keep at most 10 connections per account and at most 20 subscriptions per connection.
- Every 30 seconds the server checks the connection with a protocol-level ping — standard WebSocket clients answer it automatically.
const { data } = await fetch("https://api.avan.market/v1/user/get-ws-token", {
headers: { Authorization: `Bearer ${API_KEY}` },
}).then((response) => response.json());
const socket = new WebSocket(`wss://socket.avan.market/api?token=${data.token}`);
socket.onopen = () => {
socket.send(JSON.stringify({ action: "subscribe", channel: "catalog" }));
socket.send(JSON.stringify({ action: "subscribe", channel: `purchases:${data.user_id}` }));
};
socket.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.type === "message") {
console.log(message.channel, message.data.event, message.data);
}
};
socket.onclose = (event) => {
console.log("closed", event.code);
};
What the client sends
| Action | Message |
|---|---|
| Subscribe to a channel | {"action": "subscribe", "channel": "catalog"} |
| Unsubscribe from a channel | {"action": "unsubscribe", "channel": "catalog"} |
| Check the connection | {"action": "ping"} |
What the server sends
type | When it is sent | Other fields |
|---|---|---|
connected | Right after connecting | user_id, expires_at |
subscribed | The subscription is active | channel |
unsubscribed | The subscription is removed | channel |
message | An event in a channel | channel, data — the event itself |
pong | Reply to ping | — |
error | The client's request was not carried out | code, sometimes channel |
An event arrives in the data field of a message with type: "message". In the example above data is shortened; the examples below show its full contents.
{
"type": "message",
"channel": "catalog",
"data": {
"id": "9b2f6c1e-4d7a-4f0b-8a3e-5c1d2e7f9a40",
"price": 148.5,
"event": "skin_price_changed"
}
}
Errors and close codes
| Value | Meaning |
|---|---|
forbidden | Subscribing to someone else's private channel |
unknown_channel | No such channel |
too_many_subscriptions | More than 20 subscriptions on one connection |
invalid_json, unknown_action, message_too_large | The client's message could not be processed |
Close code 4001 | The token is missing, invalid or already expired |
Close code 4002 | The token expired while connected |
Close code 4003 | More than 10 connections per account |
Close code 4004 | The client is not reading messages fast enough |
Catalog channel
A single channel covers all games — filter by the game_id field. In the
skin_price_changed event the price field already holds the new price.
Channel
catalog
Events
| What happened | Event |
|---|---|
| A skin appeared on the market | skin_added |
| A skin was removed from sale | skin_deleted |
| A skin's price changed | skin_price_changed |
Messages for all three events share one shape: the same item object as in the
price list of the corresponding game, plus an event field with the event name. Between events only the value of event changes, while the set of fields depends on the game — switch tabs to compare.
Message — Counter-Strike 2
{
"id": "9b2f6c1e-4d7a-4f0b-8a3e-5c1d2e7f9a40",
"game_id": 730,
"name": "AWP | Asiimov (Field-Tested)",
"price": 148.5,
"delivery": 1,
"asset_id": "53540956125",
"class_id": "7993037085",
"float": "0.2744107246398926",
"paint_seed": 932,
"name_tag": null,
"inspect_link": "steam://run/730//+csgo_econ_action_preview%20B9A9415A72297CB8A1B0992EBB91BF89BD810F72114CBAF916BDDBB6B1B9A9628A842CE72507FCF5801504DBB6B1B9A9029C84A50FF207FCB9B08005DBB6B1B9A9339C841D20A007FC59E06505D13A393939B5C9B17896EAA2",
"stickers": [
{
"slot": 0,
"name": "Sticker | ZywOo (Foil) | Katowice 2019",
"wear": 0,
"image": "https://community.cloudflare.steamstatic.com/economy/image/i0CoZ81Ui0m-9KwlBY1L_18myuGuq1wfhWSaZgMttyVfPaERSR0Wqmu7LAocGJai0ki7VeTHjMGgIXSA7FVwptelsxb0SBrOhI_38i1k6f2nZOo-IvPAX2bHwrtw5rFtSii2zR9-sT7Tn4mvdC7BO1chWZckROZZska4jJS5YAEgste8"
}
],
"event": "skin_added"
}
730 — Counter-Strike 2, 570 — Dota 2,
252490 — Rust, 440 — Team Fortress 2
1 — immediately, 2 — within 12 hours
skin_added, skin_deleted or
skin_price_changed
Message — Dota 2
{
"id": "3e8a1f52-7c94-4b6d-9f20-a1d4c7e85b13",
"game_id": 570,
"name": "Dragonclaw Hook",
"price": 412.3,
"delivery": 1,
"asset_id": "29384710562",
"class_id": "57949762",
"stickers": [
{
"slot": null,
"name": "Inscribed Towers Destroyed",
"wear": null,
"image": "https://cdn.steamstatic.com/apps/570/icons/econ/sockets/gem_stat.30d7935c1f0a1b9e8e28c691c2bd28f7d5f471bc.png"
}
],
"event": "skin_price_changed"
}
730 — Counter-Strike 2, 570 — Dota 2,
252490 — Rust, 440 — Team Fortress 2
1 — immediately, 2 — within 12 hours
skin_added, skin_deleted or
skin_price_changed
Message — Rust
{
"id": "c47d9a06-2b5e-4e13-b8f7-6d0a3f91e2c5",
"game_id": 252490,
"name": "Tempered AK47",
"price": 38.5,
"delivery": 1,
"asset_id": "5193846207",
"class_id": "2143471514",
"event": "skin_deleted"
}
730 — Counter-Strike 2, 570 — Dota 2,
252490 — Rust, 440 — Team Fortress 2
1 — immediately, 2 — within 12 hours
skin_added, skin_deleted or
skin_price_changed
Message — Team Fortress 2
{
"id": "f15b7e3a-90c2-4a68-8d41-2e6c9b0a7d38",
"game_id": 440,
"name": "Mann Co. Supply Crate Key",
"price": 2.14,
"delivery": 1,
"asset_id": "14872039561",
"class_id": "101785959",
"event": "skin_added"
}
730 — Counter-Strike 2, 570 — Dota 2,
252490 — Rust, 440 — Team Fortress 2
1 — immediately, 2 — within 12 hours
skin_added, skin_deleted or
skin_price_changed
Your purchases channel
A private channel: it carries changes to your purchases only. userId is your account ID, returned together with the connection token.
Channel
purchases:{userId}
Events
| What happened | Event |
|---|---|
| A purchase's status or trade offer data changed | purchase_updated |
Message
The message contains the whole purchase — the same object returned by
/v1/market/info, plus the field event.
{
"purchase_id": "1f0c7a3e-5b2d-4c8f-9a61-3d7e2b9c4f50",
"custom_id": "order-10457",
"created_at": "2026-03-18T09:41:27.000Z",
"steam_id": "76561198319147164",
"skin": {
"id": "8f3a1d6e-b204-4c59-a6e7-1b9d5c0f7e23",
"name": "AK-47 | Slate (Field-Tested)",
"price": 3.48,
"status": "2",
"steam_trade_offer_id": "6981204573",
"error": null,
"return_reason": null,
"return_charged_commission": null
},
"event": "purchase_updated"
}
- A message always describes the current state of the purchase, so it is enough to store it over the previous one.
- The same state may arrive twice. A purchase in a final status no longer changes — messages about it can be ignored after that.
API methods
Balance
Returns the current balance of your account. The amount is in US dollars (USD).
Response
{
"data": {
"balance": 1284.37
}
}
Buy a skin
Charges the skin price to your balance and sends the skin to the recipient via a Steam trade offer. Response 200
means the purchase is created — after that, track its status. See “How a purchase works”.
partner and token come from the recipient's trade link:
https://steamcommunity.com/tradeoffer/new/?partner=358881436&token=l6LFC3R8
Parameters
Passed in the request body as JSON.
partner= in their Steam trade linktoken=duplicate_custom_id
Response
{
"data": {
"purchase_id": "1f0c7a3e-5b2d-4c8f-9a61-3d7e2b9c4f50",
"custom_id": null,
"created_at": "2026-03-18T09:41:27.000Z",
"steam_id": "76561198319147164",
"skin": {
"id": "8f3a1d6e-b204-4c59-a6e7-1b9d5c0f7e23",
"name": "AK-47 | Slate (Field-Tested)",
"price": 3.48,
"status": "0",
"steam_trade_offer_id": null,
"error": null,
"return_reason": null,
"return_charged_commission": null
}
}
}
trade_canceled{
"message": "The partner field is required. (and 1 more error)",
"errors": {
"partner": [
"The partner field is required."
],
"token": [
"The token field is required."
]
}
}
Buy errors
If the purchase is not created, no money is charged. The reason is in the field code.
| Status | code | When it occurs | Can it be retried |
|---|---|---|---|
409 | skin_unavailable | The skin is already sold or reserved by another buyer | No |
409 | price_exceeded | The skin price is higher than max_price | Yes, with a new max_price |
409 | insufficient_balance | The balance is too low | Yes, after a top-up |
409 | duplicate_custom_id | This custom_id is already taken by an earlier purchase. That purchase is returned in the field data | No need — the purchase already exists |
422 | invalid_trade_link | The partner and token do not form a valid trade link | Yes, with a correct link |
403 | account_blocked | Your account is blocked | No, contact support |
500–504 | — | A failure on the Avan Market or Steam side, the outcome is unknown | Only after checking by custom_id |
Search skins
Returns skins that can be bought right now — up to 200 per response. The next part is requested by cursor.
Parameters
730 — Counter-Strike 2, 570 — Dota 2,
252490 — Rust, 440 — Team Fortress 2
name field in full, wear included:
AWP | Asiimov (Field-Tested). No more than 100 per request
meta.next_page from the previous response
Response
{
"data": [
{
"id": "d2c5b8f1-3a46-4e70-9b1c-7e4f0a6d8c92",
"game_id": 730,
"name": "Glock-18 | Vogue (Field-Tested)",
"price": 1.86,
"delivery": 1,
"asset_id": "40217735519",
"class_id": "5114539218",
"float": "0.3127450406551361",
"paint_seed": null,
"name_tag": null,
"inspect_link": null,
"stickers": [
{
"slot": 0,
"name": "Sticker | ZywOo (Foil) | Katowice 2019",
"wear": 0,
"image": "https://community.cloudflare.steamstatic.com/economy/image/i0CoZ81Ui0m-9KwlBY1L_18myuGuq1wfhWSaZgMttyVfPaERSR0Wqmu7LAocGJai0ki7VeTHjMGgIXSA7FVwptelsxb0SBrOhI_38i1k6f2nZOo-IvPAX2bHwrtw5rFtSii2zR9-sT7Tn4mvdC7BO1chWZckROZZska4jJS5YAEgste8"
}
]
}
],
"meta": {
"per_page": 200,
"next_page": "eyJwIjoiZDJjNWI4ZjEtM2E0Ni00ZTcwLTliMWMtN2U0ZjBhNmQ4YzkyIn0"
}
}
1 — immediately, 2 — within 12 hoursnext_page. null if there are no more results
{
"message": "The selected game is invalid.",
"errors": {
"game": [
"The selected game is invalid."
]
}
}
Purchased skin statuses
Shows what is happening with your purchased skins: returns the current status of each purchase.
- At least one of the two parameters is required.
-
Purchases that are not found are simply omitted from the response — no error is returned. This is how you check for a purchase with your
custom_id. - For continuous status tracking use WebSockets, and this method for reconciliation after a disconnect.
Parameters
custom_id values passed when buying. No more than 200 per request
purchase_id values from buy responses, in UUID format. No more than 200 per request
Response
{
"data": [
{
"purchase_id": "1f0c7a3e-5b2d-4c8f-9a61-3d7e2b9c4f50",
"custom_id": null,
"created_at": "2026-03-18T09:41:27.000Z",
"steam_id": "76561198319147164",
"skin": {
"id": "8f3a1d6e-b204-4c59-a6e7-1b9d5c0f7e23",
"name": "AK-47 | Slate (Field-Tested)",
"price": 3.48,
"status": "6",
"steam_trade_offer_id": "6981204573",
"error": null,
"return_reason": "trade_canceled",
"return_charged_commission": null
}
}
]
}
trade_canceled{
"message": "The purchase ids field must not have more than 200 items.",
"errors": {
"purchase_ids": [
"The purchase ids field must not have more than 200 items."
]
}
}
Values of status
The purchase status is a string holding a numeric code. A purchase in a final status no longer changes: there is no need to track it further.
| Code | Name | Meaning | Final |
|---|---|---|---|
"0" |
Processing | The purchase is being processed, the trade has not been sent yet | No |
"2" |
Active | The trade is sent and waiting for the recipient to accept it | No |
"3" |
Accepted | The trade is accepted, the skin is delivered | Yes |
"6" |
Canceled | The trade was canceled or the purchase did not pass the review | Yes |
"7" |
Declined | The recipient declined the trade | Yes |
"8" |
InvalidItems | The item turned out to be unavailable for transfer | Yes |
"10" |
CreateFailed | The trade could not be created | Yes |
Purchase history
Returns all purchases of your account, newest first — 200 per page. Pagination is page-based.
Parameters
Response
{
"data": [
{
"purchase_id": "1f0c7a3e-5b2d-4c8f-9a61-3d7e2b9c4f50",
"custom_id": null,
"created_at": "2026-03-18T09:41:27.000Z",
"steam_id": "76561198319147164",
"skin": {
"id": "8f3a1d6e-b204-4c59-a6e7-1b9d5c0f7e23",
"name": "AK-47 | Slate (Field-Tested)",
"price": 3.48,
"status": "6",
"steam_trade_offer_id": "6981204573",
"error": null,
"return_reason": "trade_canceled",
"return_charged_commission": null
}
}
],
"meta": {
"current_page": 1,
"last_page": 6,
"per_page": 200,
"total": 1150
}
}
trade_canceled{
"message": "The start unix time field must be an integer.",
"errors": {
"start_unix_time": [
"The start unix time field must be an integer."
]
}
}
Check availability before buying
Shows which skins from the list can still be bought and at what price. The check reserves nothing: between it and the purchase the skin may go to another buyer, and the price may change.
Parameters
Response
{
"data": {
"available_skins": {
"41c7e9a2-6f58-4d03-b1a4-9e2c8d5f0b76": 0.37,
"8f3a1d6e-b204-4c59-a6e7-1b9d5c0f7e23": 3.48
},
"unavailable_skin_ids": []
}
}
{
"message": "The ids field is required.",
"errors": {
"ids": [
"The ids field is required."
]
}
}
WebSockets token
Returns a temporary token for connecting to WebSockets. Request a new token on every connection and when the previous one expires.
Response
{
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0ODIxMyIsImV4cCI6MTc3MzgzMDQ4N30.Vx3kQ9mT2rLp8sNa6fWcY1hJ4bZoEu7dG0iKqRyM5tC",
"user_id": 48213,
"expires_at": 1773830487
}
}
purchases:{userId}