Skip to main content
Alpha Feature — The Pure WebSocket API is currently in active development and is not production-stable. It may be unstable, change without notice, or be removed entirely at any time. Do not build critical production workflows on it. Contact [email protected] to be notified of changes.

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 parameters: 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 with 401 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 ping frame from your client every 8–9 seconds
Most WebSocket client libraries respond to server pings automatically (sending a 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 a subscribe 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 the event 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.
You cannot filter by variantId alone. A variantId filter is only valid when productId is also present. Sending { "variantId": "..." } without a productId silently falls back to the global topic.

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 successful subscribe action.

Unsubscription Confirmed

Sent immediately after a successful unsubscribe action.

Error

Sent when a message cannot be processed — malformed JSON, an unknown action or event type, a duplicate subscription, or an invalid filter.
Common error messages:

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 the ws package.

Python

Uses the websockets 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 volumeglobal:listings and global:offers receive every event across the entire marketplace. For most use cases, filtering by productId is 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.