Overview
The Pure WebSocket API delivers real-time orderbook events as they happen. Instead of polling the REST API, you open a single persistent connection and subscribe to the specific streams you care about. Every time a listing or offer is created, updated, or removed, your client receives a push notification within milliseconds. What you can subscribe to:Connection
Connect to the WebSocket server by opening a standard WebSocket connection with your API key passed as a query parameter:
Connection with compression enabled:
Authentication
Authentication happens at the HTTP upgrade step before the WebSocket handshake completes. If the API key is missing or invalid, the server rejects the upgrade with401 Unauthorized and the connection is never established. There is no post-connection authentication step.
Idle Timeout
The server closes idle connections after 10 seconds of inactivity. A connection is considered inactive if it receives no data (messages, pings, or pongs) within that window. To keep your connection alive, either:- Subscribe to an active high-frequency topic (listings or offers on a liquid product) so you receive regular events
- Send a WebSocket
pingframe from your client every 8–9 seconds
pong), but they do not always send their own proactive pings. Check your library’s documentation.
Sending Messages
All messages sent to the server must be JSON text frames. Binary frames are ignored.Message Format
Subscriptions
How Subscriptions Work
Each subscription maps to an internal topic. When a server-side event occurs (e.g. a listing is updated), the server publishes to all matching topics simultaneously. Your connection receives the event envelope on every topic it is subscribed to. You can hold multiple active subscriptions per connection simultaneously — for example, you can subscribe to the global offers stream and a product-scoped listings stream at the same time. Duplicate subscriptions are rejected. Sending asubscribe message for a topic you are already subscribed to returns an error response.
Topic Namespace
The server resolves your subscription request to one of the following internal topics based on theevent and filter:
Subscription Filters
Filters let you narrow a subscription to a specific product or variant. Without a filter you receive events for the entire marketplace.Subscription Examples
Subscribe to all marketplace listings
Subscribe to offers for one product
Subscribe to listings for a specific variant
Unsubscribe from a stream
Server Responses
The server sends four categories of messages back to your client.Subscription Confirmed
Sent immediately after a successfulsubscribe action.
Unsubscription Confirmed
Sent immediately after a successfulunsubscribe action.
Error
Sent when a message cannot be processed — malformed JSON, an unknown action or event type, a duplicate subscription, or an invalid filter.Realtime Event
The main payload. Sent whenever an orderbook event occurs that matches your subscriptions.
Event names:
Data Schemas
Listing (data on listing events)
Sensitive seller information is stripped before delivery. The following fields are never present in the WebSocket payload: seller_id, seller_notes, internal_id, inventory_id.
Prices are in cents (integer). Divide by 100 to get the dollar amount.
This differs from the REST API, which returns prices already converted to
dollars.
Offer (data on offer events)
Sensitive buyer information is stripped before delivery. The following fields are never present: buyer_id, buyer_notes, internal_id.
Deduplication with requestId
When a single orderbook event matches multiple topics (e.g. a listing update on prod-1/var-1 gets published to global:listings, listings:product:prod-1, and listings:product:prod-1:variant:var-1), your connection can receive the same logical event multiple times if you are subscribed to more than one matching topic.
Each event emission shares the same requestId UUID. Use it to deduplicate:
Compression
For high-frequency subscriptions, you can enable zstd compression to reduce bandwidth. Pass?compressed=true in the connection URL. When enabled:
- All messages from the server (control responses and event payloads) arrive as binary frames, zstd-compressed
- You must decompress each frame before JSON parsing
- Sending messages to the server is unchanged — always plain text JSON
The
ws Node.js library and the Python websockets library both support
binary frames natively. You need to add a zstd decompression step using a
library like @mongodb-js/zstd (Node) or zstandard / pyzstd (Python).Code Examples
Node.js
Uses thews package.
Python
Uses thewebsockets library.
Error Codes on Disconnect
The server closes connections with standard WebSocket close codes. Notable codes to handle in your client:
Implement exponential backoff on reconnect. Start with a 1–2 second delay and cap at 30–60 seconds.
Limitations (Alpha)
- No snapshot on connect — subscribing does not send you the current state of the orderbook. Use the REST API (Get Product Order Book) to fetch the current book, then subscribe to the WebSocket for subsequent deltas.
- No guaranteed delivery — if your connection drops and reconnects, events that occurred during the outage are not replayed.
- Global streams can be high volume —
global:listingsandglobal:offersreceive every event across the entire marketplace. For most use cases, filtering byproductIdis recommended. - Rate limits — no hard rate limits are currently enforced on the alpha, but excessive connections or message rates may result in disconnection without notice.