Skip to main content
This endpoint is only available to Growth and Enterprise plans.

Real-time vs HTTP

GET Method

Available in HTTP queriesUse the same filtering system in HTTP GET requests for simple queries.

POST Method

Available in HTTP queriesUse the same filtering system in HTTP POST requests for advanced configurations.

Overview

The Holders Stream provides real-time position tracking for token holders. It tracks holder positions directly from swap events and periodically resyncs from the database for accuracy.

Protocol

Endpoint Details

  • URL: wss://api.mobula.io
  • Event Type: holders

Subscription

Multiple Tokens

Parameters

  • tokens (required): Array of token subscription items, each containing:
    • address (required): Token address
    • blockchain (required): Blockchain identifier (e.g., "Solana", "evm:8453")
  • sortBy (optional, default: "balance"): Controls how the top 100 holders are sorted. Accepts "balance" (sort by USD balance descending) or "realizedPnl" (sort by realized PnL descending). Use "realizedPnl" for a top traders view
  • subscriptionId (optional): Unique identifier for your WebSocket connection. Auto-generated if not provided
  • subscriptionTracking (optional, default: false): Include subscription details in response logs for debugging
  • maxUpdatesPerMinute (optional): Throttle the number of update messages sent per minute. For example, maxUpdatesPerMinute: 30 limits updates to at most one every 2 seconds. Useful for reducing bandwidth on high-activity tokens. When not set, updates are sent as fast as they arrive (with a minimum 100ms batching interval)
Maximum 10 tokens per connection for optimal performance.

Message Types

init — Full snapshot on subscribe

Sent once when you subscribe. Contains the top 100 holders sorted by the sortBy criteria (balance by default, or realized PnL):

update — Single holder changed

Sent in real-time when a swap changes a holder’s position. Both the buyer and seller are updated:
When a holder’s balance reaches 0, the update message is sent with tokenAmount: "0". The client should remove this holder from its list.

sync — Periodic full resync

Sent every 30 seconds with a fresh snapshot from the database (same format as init). Use this to reconcile any missed updates or drift:

Data Model

Each holder object contains the following fields:

platform

Trading platform the wallet used (e.g., Photon, BullX, Maestro):

walletMetadata

Entity information from wallet labeling:

fundingInfo

Where the wallet’s initial funds came from:

Client Implementation

Key Features

  • Trades-based tracking — Positions are updated from swap events in real-time, not from external services
  • LP positions included — Liquidity pool addresses are tracked and updated with isLiquidityPool: true
  • Both sides updated — On each swap, both the buyer (recipient) and seller (sender) positions are updated
  • Post-balance accuracy — Uses on-chain post-balance from the swap for exact balance tracking
  • Periodic resync — Automatic sync from DB every 30s ensures consistency
  • Capped at 100 — Init and sync return top 100 holders, sorted by balance (default) or realized PnL via sortBy

Connection Keepalive (Ping/Pong)

To maintain active WebSocket connections and prevent timeouts: Send ping:
The server will respond with a pong message to confirm the connection is active.
Use ping messages periodically (every 30-60 seconds) to keep long-lived connections alive.

Unsubscribe

Unsubscribe from all holder streams

Unsubscribe from specific subscription

Support

Need help? Our response times are < 1h.

Support

Telegram

Support

Slack

Need help?

Email