Skip to main content
Every error returns the same JSON shape:
Note the field is detail, not message. Match on code — it is stable and safe to branch on. detail is human-readable and may be reworded without notice.
Some errors carry extra fields alongside code and detail. price_moved includes the current total, and item_unavailable may include unavailable_ids. Ignore unknown fields rather than rejecting the body.

Authentication

Rate limits

Reading market data

Buying

Webhooks

Not available through the API


Retry rules

The distinction that matters is whether money moved.

Safe to retry

429 (after Retry-After), price_updating, market_unavailable, 503, and network timeouts. Nothing was charged. Reuse the same Idempotency-Key so a request that actually succeeded replays instead of buying twice.

Do not retry unchanged

400, 401, 403, invalid_webhook_url, unsupported_item. The request is wrong; repeating it produces the same error and, on auth failures, an IP ban.

Decide, then retry

price_moved and item_unavailable. The market changed under you. Re-read the listing, apply your own pricing rule, and issue a new order with a new idempotency key.

Check before retrying

order_failed, idempotency_in_progress, and any timeout on POST. Call GET /v1/orders/info with your custom_id first — the order may already exist.
A timeout is not a failure. POST /v1/orders and POST /v1/market/buy are idempotent on Idempotency-Key / custom_id: retrying with the same value replays the original order. Retrying with a new value after a timeout is how you buy the same skin twice.