API Documentation
Browse the CS2 skin marketplace, purchase items, manage orders, and check wallet balance programmatically. All endpoints require API Token authentication.
Overview
The TradeStation Open API provides programmatic access to the CS2 skin marketplace. You can browse available inventory, execute purchases, track order status, and manage your wallet through a RESTful JSON API.
Market
Browse skins & inventory
Catalog aggregates, then list in-stock items by hash name and filters.
Trade
Purchase items
Standard buy and quick-buy; optional price checks and idempotent keys.
Orders
Track order status
List orders with status filters and fetch a single order by number.
Wallet
Balance & transactions
Snapshot of balances plus paginated history of wallet movements.
Authentication
All requests must include your API token in the Authorization header. Tokens can be generated from your account dashboard.
Authorization: Token sst_a1b2c3d4e5f6...Token format: sst_ prefix followed by 48 hex characters. The full token is only shown once at creation time — store it securely.
Base URL
https://api.tradestation.gg/api/v1All endpoint paths in this documentation are relative to this base URL.
Response Format
Every response is wrapped in a standard envelope. The top-level code field uses TradeStation business status codes (not HTTP status codes).
{
"code": 1000,
"message": "ok",
"data": { ... }
}{
"code": 3001,
"message": "Item is not available",
"data": null
}For failed/cancelled/reversed orders, the response includes both the error code and the order data:
{
"code": 5201,
"message": "Item unavailable",
"data": {
"order_no": "T20260407143022849132",
"status": "failed",
"fail_code": 5201,
...
}
}Pagination
List endpoints use page-based pagination. Control with page and page_size query parameters.
{
"code": 1000,
"message": "ok",
"count": 142,
"page": 1,
"page_size": 10,
"total_pages": 15,
"next": 2,
"previous": null,
"data": [ ... ]
}page | integer | Page number (default: 1) |
page_size | integer | Items per page (default: 10, max: 100) |
next | integer | null | Next page number, null if last page |
previous | integer | null | Previous page number, null if first page |
Rate Limiting
Requests are rate limited per user. Exceeding the limit returns HTTP 429 with code 9003.
| Endpoint | Limit |
|---|---|
GET /market/catalog | 5 / minute |
GET /market/items | 300 / minute |
POST /market/items/batch | 60 / minute |
POST /market/orders/buy | 300 / minute |
POST /market/orders/quick-buy | 300 / minute |
GET /wallet | 60 / minute |
GET /wallet/transactions | 60 / minute |
Status Codes
Business status codes are segmented by range. HTTP status codes are used conventionally (200, 201, 400, 401, 403, 404, 429, 500, 503).
1xxx — Success
1000 | ok |
1001 | Order already exists |
3xxx — Buy Pre-validation
3001 | Item is not available |
3006 | Too many active orders |
3007 | Order is being processed, please try again |
3008 | This external_order_no has already been used |
3009 | Insufficient balance |
4xxx — Quick Buy Pre-validation
4001 | Quick buy is currently disabled |
4002 | No available inventory for this item |
4003 | No available items found within the price limit |
5xxx — Order Lifecycle
5001 | Order not found |
5002 | Order status does not allow this operation |
5101 | Cancelled by admin |
5102 | Trade offer expired or platform cancelled |
5201 | Item unavailable |
5202 | Trade failed |
5301 | Trade offer creation failed |
5303 | Trade offer declined |
5304 | Steam unavailable |
5401 | Invalid trade URL |
5402 | Steam account trade restricted |
5403 | Steam inventory is private |
5501 | Trade reversed on Steam |
9xxx — System
9001 | Authentication required |
9002 | Permission denied |
9003 | Rate limit exceeded |
9004 | Invalid request body |
9005 | Missing required parameter |
9006 | Invalid parameter value |
9503 | Service temporarily unavailable, please retry shortly |
9999 | Internal server error |
API Reference
Complete endpoint reference for the TradeStation Open API.
Market Endpoints Overview
Three complementary endpoints serve different use cases:
| Endpoint | Purpose | Data freshness |
|---|---|---|
/catalog | Full-sync: aggregated min_price per skin | ~60s cache |
/items | Single skin: paginated item list with full details | Real-time |
/items/batch | Multi-skin: top 5 cheapest items per skin | Real-time |
/market/catalogReturns the aggregated overview of every skin with available inventory in a single response. Optimized for full-sync clients — served as a pre-built gzip snapshot with ETag revalidation.
No parameters required. Useful for building a skin browser — each entry represents a unique skin currently in stock, along with its lowest available price.
Response semantics
Unlike other Open API endpoints, this response is not wrapped in the standard envelope. The body is a gzip-compressed JSON object containing only the data array — the byte stream is served directly from a pre-built snapshot to keep TTFB at 1–3 ms even at multi-million-row scale.
Response headers
Content-Encoding | string | Always gzip. Decompress before parsing JSON. Standard HTTP clients (curl --compressed, fetch, requests) handle this transparently. |
ETag | string | Weak ETag of the current snapshot, e.g. W/"a1b2c3...". Send back as If-None-Match on the next request to revalidate. |
X-Snapshot-Built-At | string | UTC timestamp (seconds, ISO 8601, no timezone suffix) of when the snapshot was last rebuilt, e.g. 2026-04-25T10:30:00. |
X-Snapshot-Rows | integer | Number of rows contained in the snapshot. |
Cache-Control | string | private, max-age=30, must-revalidate — clients should hit the endpoint at most every 30 s and always revalidate via ETag. |
Response fields (per item, after gzip decompress)
hash_name | string | Steam market hash name |
phase | string | Phase variant (e.g. "Phase 2", "Ruby"). Empty for non-Doppler items. |
min_price | decimal | Lowest available price |
{
"data": [
{
"hash_name": "AK-47 | Redline (Field-Tested)",
"phase": "",
"min_price": "28.5000"
},
{
"hash_name": "★ Karambit | Doppler (Factory New)",
"phase": "Phase 2",
"min_price": "1523.0000"
}
]
}ETag revalidation (recommended)
Cache the ETag from the last successful response and send it as If-None-Match on subsequent calls. When the snapshot is unchanged, the server returns HTTP 304 Not Modified with no body — keeping bandwidth flat and your local copy fresh.
curl -H "Authorization: Token sst_..." \
-H 'If-None-Match: W/"a1b2c3..."' \
--compressed \
https://api.tradestation.example/api/v1/market/catalogSnapshot freshness
The snapshot is rebuilt by a background worker every 60 seconds. It is not event-driven — individual inventory mutations (new listing, sold, price change) do not trigger an immediate rebuild. In the worst case, catalog data can lag real-time inventory by up to ~60 s. For precise, real-time item availability and pricing, use the List Items or Batch Items endpoints.
Error: snapshot unavailable
In the rare case the snapshot has not been built yet (cold start or Redis flush), the endpoint returns HTTP 503 with the standard envelope and business code 9503. Retry after a few seconds — the worker will have rebuilt the snapshot by then.
{
"code": 9503,
"message": "Service temporarily unavailable, please retry shortly",
"data": null
}/market/itemsReturns all available listings sorted by price (lowest first), allowing you to compare and select the exact item to buy.
Query parameters
hash_namerequired | string | Steam market hash name (exact match) |
phase | string | Filter by phase (e.g. "Phase 1", "Sapphire") |
price_max | decimal | Maximum price filter |
page | integer | Page number (default: 1) |
page_size | integer | Items per page (default: 10, max: 100) |
Response fields (per item)
id | integer | Inventory item ID (use for purchase) |
hash_name | string | Steam market hash name |
name_zh | string | Chinese name |
phase | string | Phase variant |
price | decimal | Selling price (CNY, 4 decimal places) |
float_value | decimal | null | Float value (up to 18 decimal places) |
paint_seed | integer | null | Paint seed |
paint_index | integer | null | Paint index |
name_tag | string | Applied name tag |
stickers | array | Applied stickers |
charm | array | Attached charms (keychain slot) |
GET /api/v1/market/items?hash_name=Souvenir+Galil+AR+%7C+Green+Apple+(Factory+New)&page_size=2Rows are sampled from real listings for the same hash_name (IDs and stock change over time). stickers / charm drop skin_id and image_url. Some sources expose market_hash_name plus placement floats; others expose a display name only. The second list entry omits attachment bodies and uses [ ... ] as a shorthand.
{
"code": 1000,
"message": "ok",
"count": 11,
"page": 1,
"page_size": 2,
"total_pages": 6,
"next": 2,
"previous": null,
"data": [
{
"id": 40310,
"hash_name": "Souvenir Galil AR | Green Apple (Factory New)",
"name_zh": "加利尔AR(纪念品) | 绿苹果 (崭新出厂)",
"phase": "",
"price": "10.2500",
"float_value": "0.034173440188169479",
"paint_seed": 780,
"paint_index": 294,
"name_tag": "",
"stickers": [
{
"name": " StarLadder(金色)| 2025年布达佩斯锦标赛",
"slot": 0,
"wear": "0"
},
{
"name": " 火车(金色)",
"slot": 2,
"wear": "0"
},
{
"name": " Natus Vincere(金色)| 2025年布达佩斯锦标赛",
"slot": 1,
"wear": "0"
},
{
"name": " FURIA(金色)| 2025年布达佩斯锦标赛",
"slot": 3,
"wear": "0"
}
],
"charm": [
{
"name": "挂件(纪念品): 2025年布达佩斯锦标赛高光时刻 | YEKINDAR对阵Natus Vincere Train精彩表现",
"pattern": null
}
]
},
{
"id": 40311,
"hash_name": "Souvenir Galil AR | Green Apple (Factory New)",
"name_zh": "加利尔AR(纪念品) | 绿苹果 (崭新出厂)",
"phase": "",
"price": "10.2500",
"float_value": "0.060612890869379043",
"paint_seed": 803,
"paint_index": 294,
"name_tag": "",
"stickers": [ ... ],
"charm": [ ... ]
}
]
}/market/items/batchBatch query multiple skins at once. Returns up to 5 lowest-priced items per skin. Useful for checking availability and pricing across many skins in a single request.
When to use
Use this endpoint when you need real-time prices for multiple skins simultaneously (e.g. refreshing a watchlist, comparing prices, or pre-checking stock before bulk purchases). It queries the database directly with no caching — results are always up-to-date.
Request body
itemsrequired | array | Array of query objects (1–50 entries) |
items[].hash_namerequired | string | Steam market hash name (exact match) |
items[].phase | string | Optional phase filter (e.g. "Phase 2", "Sapphire") |
Response format
The data field is an object keyed by skin identifier. Each value is an array of up to 5 items sorted by price ascending. Skins not found or with no available stock return an empty array. Response key is hash_name when no phase is specified, or hash_name + phase (concatenated directly, no separator) when phase is present.
Item fields are identical to List Items: id, hash_name, name_zh, phase, price, float_value, paint_seed, paint_index, name_tag, stickers, charm.
POST /api/v1/market/items/batch
Content-Type: application/json
Authorization: Token sst_a1b2c3d4e5f6...
{
"items": [
{"hash_name": "AK-47 | Redline (Field-Tested)"},
{"hash_name": "★ Karambit | Doppler (Factory New)", "phase": "Phase 2"},
{"hash_name": "Non-Existent Skin"}
]
}{
"code": 1000,
"message": "ok",
"data": {
"AK-47 | Redline (Field-Tested)": [
{
"id": 12001,
"hash_name": "AK-47 | Redline (Field-Tested)",
"name_zh": "AK-47 | 红线 (久经沙场)",
"phase": "",
"price": "28.5000",
"float_value": "0.256312847137451170",
"paint_seed": 661,
"paint_index": 282,
"name_tag": "",
"stickers": [],
"charm": []
},
{
"id": 12042,
"hash_name": "AK-47 | Redline (Field-Tested)",
"name_zh": "AK-47 | 红线 (久经沙场)",
"phase": "",
"price": "29.1200",
"float_value": "0.180000000000000000",
"paint_seed": 123,
"paint_index": 282,
"name_tag": "",
"stickers": [ ... ],
"charm": []
}
],
"★ Karambit | Doppler (Factory New)Phase 2": [
{
"id": 8821,
"hash_name": "★ Karambit | Doppler (Factory New)",
"name_zh": "★ 爪子刀 | 多普勒 (崭新出厂)",
"phase": "Phase 2",
"price": "1523.0000",
"float_value": "0.008221340179443359",
"paint_seed": 420,
"paint_index": 418,
"name_tag": "",
"stickers": [],
"charm": []
}
],
"Non-Existent Skin": []
}
}Important: Asynchronous Fulfillment
Both buy and quick-buy are asynchronous operations. A successful response (code: 1000, status: "created") means the order has been accepted and funds have been frozen — it does not mean the Steam trade offer has been sent yet. The system will attempt to send the trade offer in the background; the order will transition to pending once the offer is dispatched successfully.
Poll GET /market/orders/{order_no} to track fulfillment progress. Orders that remain unaccepted will be automatically cancelled after 40 minutes (default timeout).
/market/orders/buyPurchase a specific inventory item by ID. The item will be delivered to your Steam trade URL.
Request body
item_idrequired | integer | Inventory item ID (from market listing) |
trade_urlrequired | string | Steam trade URL (https://steamcommunity.com/tradeoffer/new/?partner=...&token=...) |
external_order_no | string | Your external order reference (max 64 chars, must be unique per user) |
Idempotency
If a request with the same item_id (or same external_order_no) finds an existing active order, the API returns that order with code 1001 instead of creating a duplicate.
POST /api/v1/market/orders/buy
Content-Type: application/json
Authorization: Token sst_a1b2c3d4e5f6...
{
"item_id": 4821,
"trade_url": "https://steamcommunity.com/tradeoffer/new/?partner=123456&token=AbCdEf",
"external_order_no": "my-order-001"
}{
"code": 1000,
"message": "ok",
"data": {
"order_no": "T20260407143022849132",
"external_order_no": "my-order-001",
"status": "created",
"price": "28.5000",
"hash_name": "AK-47 | Redline (Field-Tested)",
"name_zh": "AK-47 | 红线 (久经沙场)",
"phase": "",
"float_value": "0.256312847137451170",
"paint_seed": 661,
"paint_index": 282,
"name_tag": "",
"stickers": [...],
"charm": [],
"fail_code": null,
"fail_reason_display": "",
"created_at": "2026-04-07T14:30:22.849132Z",
"completed_at": null
}
}/market/orders/quick-buyPurchase the lowest-priced available item for a given skin. Automatically selects the cheapest item.
Request body
hash_namerequired | string | Steam market hash name |
trade_urlrequired | string | Steam trade URL |
phase | string | Limit to a specific phase |
max_price | decimal | Maximum acceptable price — returns 4003 if no items below this price |
external_order_no | string | Your external order reference (max 64 chars) |
POST /api/v1/market/orders/quick-buy
Content-Type: application/json
Authorization: Token sst_a1b2c3d4e5f6...
{
"hash_name": "AK-47 | Redline (Field-Tested)",
"trade_url": "https://steamcommunity.com/tradeoffer/new/?partner=123456&token=AbCdEf",
"max_price": "30.0000"
}Response format is identical to the Buy Item endpoint.
/market/ordersLists your orders with optional filtering by status, external order number, and date range. Ordered by creation time descending. Each row uses the same order object shape as GET /market/orders/{order_no} (nested skin metadata plus instance fields).
Query parameters
status | string | Filter by order status: created pending completed failed cancelled reversed |
external_order_no | string | Filter by your external order reference (exact match) |
start_date | string | Start date inclusive (ISO 8601 format: YYYY-MM-DD) |
end_date | string | End date inclusive (ISO 8601 format: YYYY-MM-DD) |
page | integer | Page number (default: 1) |
page_size | integer | Items per page (default: 10, max: 100) |
Date range cannot exceed 90 days. Both start_date and end_date are optional and can be used independently.
Response fields (per order)
order_no | string | TradeStation order number |
external_order_no | string | Your external reference |
status | string | Order status |
price | decimal | Transaction price |
hash_name | string | Skin market hash name |
name_zh | string | Chinese name |
phase | string | Phase variant |
float_value | decimal | null | Item float (this instance) |
paint_seed | integer | null | Item paint seed |
paint_index | integer | null | Item paint index |
name_tag | string | Applied name tag on the item |
stickers | array | Stickers JSON (same storage shape as market listings) |
charm | array | Charms / keychain slot JSON |
fail_code | integer | null | Failure code (5xxx) if applicable |
fail_reason_display | string | Human-readable failure reason |
created_at | datetime | ISO 8601 timestamp |
completed_at | datetime | null | Completion time |
GET /api/v1/market/orders?status=completed&page=1&page_size=10{
"code": 1000,
"message": "ok",
"count": 24,
"page": 1,
"page_size": 10,
"total_pages": 3,
"next": 2,
"previous": null,
"data": [
{
"order_no": "T20260415120000123456",
"external_order_no": "inv-2026-0415-001",
"status": "completed",
"price": "28.5000",
"hash_name": "AK-47 | Redline (Field-Tested)",
"name_zh": "AK-47 | 红线 (久经沙场)",
"phase": "",
"float_value": "0.256312847137451170",
"paint_seed": 661,
"paint_index": 282,
"name_tag": "",
"stickers": [
{
"slot": 0,
"wear": null,
"market_hash_name": "Sticker | iBUYPOWER (Holo) | Katowice 2014",
"offset_x": -0.08,
"offset_y": 0.02,
"rotation": null
}
],
"charm": [],
"fail_code": null,
"fail_reason_display": "",
"created_at": "2026-04-15T10:12:03.123456Z",
"completed_at": "2026-04-15T10:18:44.987654Z"
},
{
"order_no": "T20260415104500987654",
"external_order_no": "",
"status": "pending",
"price": "120.7143",
"hash_name": "AWP | Chrome Cannon (Factory New)",
"name_zh": "AWP | 镀铬大炮 (崭新出厂)",
"phase": "",
"float_value": "0.069282613694667820",
"paint_seed": 946,
"paint_index": 1170,
"name_tag": "",
"stickers": [ ... ],
"charm": [ ... ],
"fail_code": null,
"fail_reason_display": "",
"created_at": "2026-04-15T09:45:22.100000Z",
"completed_at": null
}
]
}/market/orders/{order_no}Retrieve a single order. Response body matches one element from GET /market/orders (same fields and nesting).
Path parameters
order_norequired | string | TradeStation order number or your external_order_no. The API first tries to match by system order number; if not found, it falls back to your external reference. |
Field list is identical to each object in the order list — same flat skin fields (hash_name, name_zh, phase) plus instance attributes (float_value, paint_*, name_tag, stickers, charm).
For orders in terminal states (failed, cancelled, reversed), the top-level code will be the fail_code (5xxx) instead of 1000.
GET /api/v1/market/orders/T20260415120000123456GET /api/v1/market/orders/inv-2026-0415-001{
"code": 1000,
"message": "ok",
"data": {
"order_no": "T20260415120000123456",
"external_order_no": "inv-2026-0415-001",
"status": "completed",
"price": "28.5000",
"hash_name": "AK-47 | Redline (Field-Tested)",
"name_zh": "AK-47 | 红线 (久经沙场)",
"phase": "",
"float_value": "0.256312847137451170",
"paint_seed": 661,
"paint_index": 282,
"name_tag": "",
"stickers": [
{
"slot": 0,
"wear": null,
"market_hash_name": "Sticker | iBUYPOWER (Holo) | Katowice 2014",
"offset_x": -0.08,
"offset_y": 0.02,
"rotation": null
}
],
"charm": [],
"fail_code": null,
"fail_reason_display": "",
"created_at": "2026-04-15T10:12:03.123456Z",
"completed_at": "2026-04-15T10:18:44.987654Z"
}
}stickers / charm mirror the stored attachment JSON (same shapes as in List Items); empty arrays when none.
{
"code": 5201,
"message": "Item unavailable",
"data": {
"order_no": "T20260414083000555666",
"external_order_no": "",
"status": "failed",
"price": "15.0000",
"hash_name": "M4A4 | Howl (Field-Tested)",
"name_zh": "M4A4 | 咆哮 (久经沙场)",
"phase": "",
"float_value": "0.180000000000000000",
"paint_seed": 100,
"paint_index": 419,
"name_tag": "",
"stickers": [],
"charm": [],
"fail_code": 5201,
"fail_reason_display": "Item unavailable",
"created_at": "2026-04-14T08:30:00.000000Z",
"completed_at": null
}
}/walletReturns your current wallet balance snapshot including available, held, and frozen amounts.
Response fields
currency | string | Wallet currency (always USD) |
available | decimal | Available balance — can be used for trading and withdrawal |
held | decimal | Held balance — credited but in hold period, can trade but cannot withdraw |
frozen | decimal | Frozen balance — locked for pending orders, cannot trade or withdraw |
total | decimal | Total balance (available + held + frozen) |
tradable | decimal | Tradable balance (available + held) |
withdrawable | decimal | Withdrawable balance (available only) |
status | string | Wallet status: active or frozen |
updated_at | datetime | Last balance update time (ISO 8601) |
{
"code": 1000,
"message": "ok",
"data": {
"currency": "USD",
"available": "8997.868000",
"held": "0.000000",
"frozen": "1.066000",
"total": "8998.934000",
"tradable": "8997.868000",
"withdrawable": "8997.868000",
"status": "active",
"updated_at": "2026-04-14T16:18:46.915184Z"
}
}/wallet/transactionsLists your wallet transactions in reverse chronological order. Supports filtering by type and date range.
Query parameters
tx_type | string | Filter by transaction type: deposit withdraw trade_freeze trade_unfreeze trade_pay trade_income adjustment transfer_in transfer_out etc. |
start_date | string | Start date inclusive (ISO 8601 format: YYYY-MM-DD) |
end_date | string | End date inclusive (ISO 8601 format: YYYY-MM-DD) |
page | integer | Page number (default: 1) |
page_size | integer | Items per page (default: 100, max: 100) |
Date range cannot exceed 31 days. If only start_date is provided, end date defaults to start + 31 days (or today). If only end_date is provided, start date defaults to end − 31 days.
Response fields (per transaction)
tx_no | string | Transaction reference number |
tx_type | string | Transaction type |
amount | decimal | Change amount (positive = credit, negative = debit) |
balance_before | decimal | Available balance before this transaction |
held_before | decimal | Held balance before this transaction |
frozen_before | decimal | Frozen balance before this transaction |
balance_after | decimal | Available balance after this transaction |
held_after | decimal | Held balance after this transaction |
frozen_after | decimal | Frozen balance after this transaction |
biz_type | string | Business type (e.g. trade_freeze, adjustment) |
biz_id | string | Related business reference (e.g. order number) |
description | string | Human-readable description |
created_at | datetime | Transaction time (ISO 8601) |
GET /api/v1/wallet/transactions?start_date=2026-04-01&end_date=2026-04-14&page_size=2{
"code": 1000,
"message": "ok",
"count": 15,
"page": 1,
"page_size": 2,
"total_pages": 8,
"next": 2,
"previous": null,
"data": [
{
"tx_no": "WT2026041479108331",
"tx_type": "trade_unfreeze",
"amount": "1.660500",
"balance_before": "8996.207500",
"held_before": "0.000000",
"frozen_before": "2.726500",
"balance_after": "8997.868000",
"held_after": "0.000000",
"frozen_after": "1.066000",
"biz_type": "trade_unfreeze",
"biz_id": "T20260414154317644080",
"description": "",
"created_at": "2026-04-14T16:18:46.917017Z"
},
{
"tx_no": "WT2026041433429418",
"tx_type": "trade_freeze",
"amount": "-1.660500",
"balance_before": "8997.868000",
"held_before": "0.000000",
"frozen_before": "1.066000",
"balance_after": "8996.207500",
"held_after": "0.000000",
"frozen_after": "2.726500",
"biz_type": "trade_freeze",
"biz_id": "T20260414154317644080",
"description": "",
"created_at": "2026-04-14T15:43:17.378123Z"
}
]
}Order Status Flow
createdpendingcompletedcreatedfailedPre-execution failure (item unavailable, insufficient balance, etc.)pendingcancelledTrade offer expired or cancelled by adminpendingfailedBuyer declined trade offer or technical failurecompletedreversedCompleted trade reversed on SteamOrders that are still waiting on buyer-side action (e.g. trade offer acceptance) will be automatically cancelled after 40 minutes. Make sure to accept the Steam trade offer within this window to avoid cancellation.
createdOrder created, executing purchase
pendingTrade offer sent, awaiting acceptance
completedTrade completed successfully
failedTrade failed permanently
cancelledCancelled by timeout or admin
reversedCompleted trade reversed on Steam
Integration Best Practices
Use external_order_no for idempotency
Always pass your own unique order reference. If a network error occurs mid-request, retrying with the same external_order_no will return the existing order (code 1001) instead of creating a duplicate.
Use max_price for price protection (quick-buy)
Prices can change between browsing and purchasing. Set max_price in the quick-buy endpoint to reject the trade if the price exceeds your limit.
Poll order status for async fulfillment
Orders transition from created → pending → completed asynchronously. Poll GET /market/orders/{order_no} to track progress. Use exponential backoff starting from 5 seconds.
Handle 5xxx codes in order responses
Terminal order responses (failed/cancelled/reversed) return 5xxx codes at the top level. Check the code field before parsing data to handle failures gracefully.
Respect rate limits
If you receive code 9003, back off and retry after the indicated period. Persistent rate limiting violations may result in token revocation.