Skip to main content
AssetPay provides a Socket.IO WebSocket connection for real-time updates. Use it to push trade status changes and price updates to your frontend without polling.

Connecting

Connect using Socket.IO with your API key, a client token, or a merchant dashboard access token: With API key (merchant-level access):
With client token (user-level access):
With merchant access token (dashboard JWT):
All three methods join the same merchant room and receive the same trade, deposit, and withdrawal events. Use whichever is more convenient for your architecture. Admin credentials don’t join a merchant room and never receive market updates. One exception: market updates are delivered only to merchant API key connections where the key has the CORE_ACCESS scope. Client token and access token connections never receive them.

Socket.IO Client Example

Events

Trade Updates

Fired whenever a trade changes status. This is the most important event for keeping your UI in sync.
The data.trade object is the same Trade shape you see in callbacks and API responses. Trade events are not game-specific. You’ll receive updates for all games (CS2 and Rust) on the same connection.

Crypto Deposit Updates

Fired when a merchant crypto deposit changes state:

Crypto Withdrawal Updates

Fired when a merchant crypto withdrawal changes state:

Market Updates

Fired when the market changes: an item becomes available, an existing item changes (typically its price), an item is no longer available, or the market is rebuilt. This mirrors what GET /secure/market returns, so you can keep a local copy current without polling. Both CS2 (730) and Rust (252490) publish market updates on the same connection and the same envelope. Key your local state on game as well as item.id, and ignore events for games you don’t offer. Market updates require an API key connection where the key has the CORE_ACCESS scope. Client token connections do not receive this event.
Notes on applying events:
  • Every new connection first receives { "type": "sync", "reason": "subscribe" } with no game or source. Events sent while you were disconnected are not replayed, so treat it as a signal to refetch every game you offer.
  • upsert and patch both carry the full item. Apply either as an idempotent upsert keyed on item.id; the distinction only signals whether the item is new or changed. Rust never emits patch, so never branch on which of the two you received.
  • A remove can arrive for an item you never saw. Ignore it in that case.
  • On a sync with reason: "feed", your local view for that game may be arbitrarily stale. Refetch GET /secure/market?game=<game> and rebuild from the response. Such a sync affects only the game it names; leave the other game’s state alone.
  • A price change does not always arrive as a patch. Where an item’s id is tied to the price it is offered at, the same change arrives as a remove of the old entry followed by an upsert of a new one. Apply events in the order received.
  • CS2 prices are per merchant account, so the offer.price you receive already reflects your fee. Rust events carry the price at the default fee, while GET /secure/market?game=252490 applies your account’s fee, so the two can differ when your fee is not the default. Still validate the price at purchase time as described in Market.

WebSocket vs Callbacks

Both WebSocket and callbacks deliver trade updates. They serve different purposes: Use both. WebSocket for instant UI feedback, callbacks for the authoritative balance updates. Don’t process balance changes based on WebSocket events alone.

Connection Notes

  • Only the websocket transport is supported (no HTTP long-polling fallback)
  • The connection authenticates once on connect. If your token expires, reconnect with a fresh one.
  • All events are scoped to your merchant account. You only see your own trades.