Historical Holders & Transfers

Track token holder count and transfer volume trends over time. This data is essential for growth analysis, adoption metrics, and detecting accumulation or distribution phases before they're reflected in price.

Why Historical Holder Data Matters

Holder count is one of the most important leading indicators for token health:

  • Growing holders often precede price appreciation as adoption increases
  • Declining holders can signal distribution or loss of interest
  • Volume spikes may indicate whale activity or upcoming volatility
  • Holder velocity (rate of change) reveals momentum

Unlike price data which reacts instantly to trades, holder metrics move more slowly and can provide early signals of fundamental shifts in a token's community.


Endpoints

EndpointDescription
GET /tokens/{mint}/holders-tsHolder count over time
GET /tokens/{mint}/volume-tsTransfer volume over time

Holder Count History

Track how many unique addresses hold a token over time.

Parameters

ParameterTypeDescription
mintAddressstringToken mint public key (required)
intervalstringTime granularity: day or hour
startTimenumberStart of range (Unix timestamp)
endTimenumberEnd of range (Unix timestamp)
limitnumberResults per page
pagenumberPage number (0-indexed)

Example Request

curl "https://api.vybenetwork.com/tokens/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/holders-ts?interval=day&limit=30" \
  -H "X-API-Key: YOUR_API_KEY"

Example Response

{
  "mintAddress": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
  "symbol": "BONK",
  "data": [
    {
      "timestamp": "2024-01-15T00:00:00Z",
      "holderCount": 892345,
      "change": 1234
    },
    {
      "timestamp": "2024-01-14T00:00:00Z",
      "holderCount": 891111,
      "change": 2345
    }
  ]
}

Response Fields

FieldDescription
timestampDate/time of the snapshot
holderCountTotal unique holders at this time
changeNet change from previous period

Volume History

Track transfer volume in USD over time—useful for identifying periods of high activity.

Parameters

ParameterTypeDescription
mintAddressstringToken mint public key (required)
intervalstringTime granularity: day or hour
startTimenumberStart of range (Unix timestamp)
endTimenumberEnd of range (Unix timestamp)
limitnumberResults per page
pagenumberPage number (0-indexed)

Example Request

curl "https://api.vybenetwork.com/tokens/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/volume-ts?interval=day&limit=30" \
  -H "X-API-Key: YOUR_API_KEY"

Example Response

{
  "mintAddress": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
  "symbol": "BONK",
  "data": [
    {
      "timestamp": "2024-01-15T00:00:00Z",
      "volumeUsd": "12345678.90",
      "transactionCount": 45678
    },
    {
      "timestamp": "2024-01-14T00:00:00Z",
      "volumeUsd": "10234567.89",
      "transactionCount": 42345
    }
  ]
}

Common Use Cases

Use CaseImplementation
Growth ChartsPlot holder count for token dashboards
Adoption MetricsTrack daily new holders for reports
Volume AnalysisIdentify unusual activity periods
Research ReportsHistorical data for due diligence
Alert SystemsTrigger on growth rate changes
Trend DetectionFind tokens with accelerating adoption

Growth Analysis Example

Calculate comprehensive growth metrics:

async function analyzeTokenGrowth(mintAddress, days = 30) {
  const response = await fetch(
    `https://api.vybenetwork.com/tokens/${mintAddress}/holders-ts?interval=day&limit=${days}`,
    { headers: { "X-API-Key": API_KEY } }
  );
  const { data, symbol } = await response.json();
  
  // Sort chronologically (oldest first)
  const sorted = [...data].reverse();
  
  // Basic metrics
  const startHolders = sorted[0].holderCount;
  const endHolders = sorted[sorted.length - 1].holderCount;
  const totalGrowth = endHolders - startHolders;
  const percentGrowth = ((totalGrowth / startHolders) * 100);
  const avgDaily = totalGrowth / days;
  
  // Best and worst days
  const bestDay = sorted.reduce((max, d) => d.change > max.change ? d : max);
  const worstDay = sorted.reduce((min, d) => d.change < min.change ? d : min);
  
  // Growth velocity (is growth accelerating or slowing?)
  const firstHalf = sorted.slice(0, Math.floor(days / 2));
  const secondHalf = sorted.slice(Math.floor(days / 2));
  const firstHalfGrowth = firstHalf.reduce((sum, d) => sum + d.change, 0);
  const secondHalfGrowth = secondHalf.reduce((sum, d) => sum + d.change, 0);
  const accelerating = secondHalfGrowth > firstHalfGrowth;
  
  return {
    symbol,
    period: `${days} days`,
    startHolders: startHolders.toLocaleString(),
    endHolders: endHolders.toLocaleString(),
    totalGrowth: totalGrowth.toLocaleString(),
    percentGrowth: `${percentGrowth.toFixed(2)}%`,
    avgDailyGrowth: Math.round(avgDaily).toLocaleString(),
    bestDay: {
      date: bestDay.timestamp.split('T')[0],
      added: bestDay.change.toLocaleString()
    },
    worstDay: {
      date: worstDay.timestamp.split('T')[0],
      added: worstDay.change.toLocaleString()
    },
    momentum: accelerating ? "Accelerating 📈" : "Decelerating 📉"
  };
}

Volume Trend Chart

Build a volume chart for your token dashboard:

async function getVolumeChart(mintAddress, days = 30) {
  const response = await fetch(
    `https://api.vybenetwork.com/tokens/${mintAddress}/volume-ts?interval=day&limit=${days}`,
    { headers: { "X-API-Key": API_KEY } }
  );
  const { data } = await response.json();
  
  // Format for charting library (Chart.js, Recharts, etc.)
  const chartData = data.reverse().map(d => ({
    date: new Date(d.timestamp),
    label: d.timestamp.split('T')[0],
    volume: parseFloat(d.volumeUsd),
    transactions: d.transactionCount
  }));
  
  // Calculate moving average
  const movingAvg = chartData.map((point, i) => {
    const window = chartData.slice(Math.max(0, i - 6), i + 1);
    const avg = window.reduce((sum, p) => sum + p.volume, 0) / window.length;
    return { ...point, movingAvg: avg };
  });
  
  return movingAvg;
}

Correlation Analysis

Compare holder growth with price action to find patterns:

async function correlateHoldersAndPrice(mintAddress) {
  const [holders, candles] = await Promise.all([
    fetch(`https://api.vybenetwork.com/tokens/${mintAddress}/holders-ts?interval=day&limit=30`, {
      headers: { "X-API-Key": API_KEY }
    }),
    fetch(`https://api.vybenetwork.com/tokens/${mintAddress}/candles?resolution=1d&limit=30`, {
      headers: { "X-API-Key": API_KEY }
    })
  ].map(p => p.then(r => r.json())));
  
  // Combine data by date
  const combined = holders.data.map(h => {
    const date = h.timestamp.split('T')[0];
    const candle = candles.data.find(c => c.timestamp.split('T')[0] === date);
    
    return {
      date,
      holderChange: h.change,
      holderCount: h.holderCount,
      priceChange: candle 
        ? ((parseFloat(candle.close) - parseFloat(candle.open)) / parseFloat(candle.open) * 100).toFixed(2)
        : null,
      price: candle ? parseFloat(candle.close) : null
    };
  });
  
  // Find days where holders grew but price didn't (potential opportunity)
  const divergences = combined.filter(d => 
    d.holderChange > 100 && parseFloat(d.priceChange) < 0
  );
  
  return { combined, divergences };
}

Anomaly Detection

Detect unusual holder activity:

async function detectHolderAnomalies(mintAddress) {
  const response = await fetch(
    `https://api.vybenetwork.com/tokens/${mintAddress}/holders-ts?interval=day&limit=30`,
    { headers: { "X-API-Key": API_KEY } }
  );
  const { data } = await response.json();
  
  // Calculate mean and standard deviation
  const changes = data.map(d => d.change);
  const mean = changes.reduce((a, b) => a + b, 0) / changes.length;
  const stdDev = Math.sqrt(
    changes.reduce((sq, n) => sq + Math.pow(n - mean, 2), 0) / changes.length
  );
  
  // Flag days with changes > 2 standard deviations
  const anomalies = data.filter(d => 
    Math.abs(d.change - mean) > 2 * stdDev
  ).map(d => ({
    date: d.timestamp,
    change: d.change,
    type: d.change > mean ? 'SURGE' : 'DROP',
    deviation: ((d.change - mean) / stdDev).toFixed(2)
  }));
  
  return {
    avgDailyChange: Math.round(mean),
    stdDeviation: Math.round(stdDev),
    anomalies
  };
}

Related Endpoints