Skip to main content
Every trade follows a state machine. Understanding the status transitions is critical for correctly handling callbacks and updating your users.

Trade Statuses

There is no partial status. pending and active are emitted on withdrawals as the supplier sources the item and the Steam offer is sent, and deposits can emit pending too. Statuses are atomic per trade: for multi-item withdrawals, each item carries its own status field but the trade-level status is always one of the values above.

Deposit Status Flow

What triggers each transition:

  • initiated → pending: The Steam offer was created and is waiting for the sending bot’s confirmation
  • initiated → active: Steam trade offer sent to the user, sitting in their Steam inbox, awaiting acceptance
  • initiated → failed / canceled: Bot dispatch failed or the trade was canceled before the offer left
  • initiated → declined: The offer was declined before active was recorded
  • pending → active: The bot confirmed the offer; it is now in the user’s Steam inbox
  • pending → hold / completed: The user accepted before active was recorded (completed directly for Rust)
  • pending → failed / canceled / declined: The unconfirmed offer failed, was canceled, or was declined
  • active → hold: User accepted, items received, Steam hold period started
  • active → failed: Trade offer expired or the user’s account has restrictions
  • active → declined: User actively declined the Steam trade offer
  • active → canceled: Offer auto-canceled after sitting unaccepted past its window, or an admin/user canceled it
  • hold → completed: 7-day hold ended with no reversal, plus a short settlement buffer
  • hold → reverted: Items were clawed back during the hold window. This is where a reversal normally happens (check revertedBy)
  • hold → failed: Steam reported the trade as failed during the hold
  • completed → reverted: A late reversal reported after the hold already settled (uncommon; check revertedBy)
active ≠ “user accepted”. active means we sent the trade offer and it’s sitting in the user’s Steam inbox. The user-accepted moment is active → hold.
A reversal lands during hold, not after completed. completed is only entered once the hold window has passed and a short settlement buffer on top, because Steam can still roll a trade back right up to settlement. A completed → reverted edge exists for a late reversal reported after that point, but it is rare, so build for hold → reverted.
Rust deposits skip the hold step. Rust items don’t have a 7-day Steam protection window, so a successful Rust deposit transitions active → completed directly.

Withdrawal Status Flow

What triggers each transition:

  • initiated → pending: Merchant approved via the initiated callback; AssetPay starts sourcing the item from the supplier
  • initiated → failed: Merchant rejected via callback (4xx response or rejection body), the approval callback got no answer after 3 attempts (APPROVAL_TIMEOUT), the callback URL or API secret was removed after the trade was created, or the supplier purchase failed. A merchant with no usable callback URL or API secret at request time gets an HTTP error instead (MERCHANT_NO_CALLBACK_URL, MERCHANT_CALLBACK_URL_DISABLED, MERCHANT_NO_API_SECRET) and no trade is created
  • initiated → canceled: Trade explicitly canceled before processing
  • pending → active: Item sourced, Steam trade offer sent to the user, awaiting acceptance
  • pending → failed: Supplier purchase could not be completed
  • pending → canceled: The item was canceled (manually or by auto-cancel) before the offer was sent
  • active → hold: User accepted the Steam trade offer, Steam hold period started
  • active → failed: The Steam offer expired or the recipient’s account is restricted
  • active → declined: The end user actively declined the Steam offer (your merchant wallet is refunded)
  • hold → completed: 7-day hold ended, no reversal detected
  • hold → failed: Items reversed by Steam during the hold period
  • hold → reverted: Trade was reversed by the supplier or user during the hold period (check revertedBy)
  • completed → reverted: Trade was reversed after the hold completed
A withdrawal moves initiated → pending → active → hold → completed. Not every trade emits every intermediate status, so treat pending and active as progress signals and drive balance changes off initiated (deduct) and the terminal states.
Rust withdrawals normally skip the hold step. Rust items have no 7-day reversal-protection window, so a successful Rust withdrawal usually transitions active → completed directly, with no holdEndDate. The exception is a Steam security escrow (recipient has no mobile authenticator), which surfaces as hold. CS2 withdrawals always go through hold, which carries offerID + holdEndDate.

The 7-Day Hold

Steam enforces a 7-day reversal window on CS2 trades. During this window, items can be clawed back. This affects how you should handle balance credits. The holdEndDate field on the trade object tells you exactly when the hold expires. Without instant deposits: Don’t credit any balance until completed. Simple and safe. With instant deposits (recommended): When a deposit enters hold, the trade includes:
  • preCredit: amount to credit immediately (calculated from collateral)
  • pendingCredit: remaining amount to credit after the hold
Credit preCredit on hold, then credit pendingCredit on completed. If the trade gets reverted, reverse only what you have already credited: preCredit if it is reverted during hold (the normal case), both if it is reverted after completed. Rust deposits skip the hold entirely: a Rust trade carries preCredit equal to totalPrice and pendingCredit 0, so credit totalPrice on completed.

Terminal States

These statuses are final and won’t change:
  • completed: The trade is done. Balance has been settled. (Can still transition to reverted if Steam reverses the trade afterward.)
  • canceled: The trade was canceled before processing started. No balance settlement.
  • declined: The end user declined the trade offer. Deposits: no items received, no settlement. Withdrawals (CS2 only): delivery didn’t happen. Items AssetPay fills from its own stock are refunded in full; items bought from a marketplace are refunded minus the penalty the marketplace kept, so this can refund less than failed. A declined Rust offer ends as failed.
  • failed: The trade didn’t go through. For withdrawals where you previously deducted the user’s balance, refund it.
  • reverted: The trade was reversed after being settled. Check revertedBy to understand who initiated it.

The revertedBy Field

When a trade reaches reverted, the revertedBy field tells you who caused it: For deposits, a reversal normally happens during hold, when Steam rolls the trade back, and revertedBy is set to user. For withdrawals, either value can appear after acceptance; see Trade Reversals for what each means for your merchant wallet.

Bot Info

During certain stages, the trade object includes botInfo with details about the Steam bot handling the trade:
You can show this in your UI so users know which bot to expect the trade offer from. You probably don’t want to expose all internal statuses to your users. Here’s a suggested mapping: