Cambrian Token Holders Over Time API
GET /api/v1/solana/tokens/holders-over-time
Token Holders Over Time
Overview
Returns a list of accounts holding a specific token (identified by its program ID/mint address) on Solana. It returns snapshots at specified block intervals within a given range: the first block returns the full list of holders, while subsequent blocks only return holders whose balance changed during that interval. Results are sorted by block number (ascending) and then balance (descending) within each block.
Business Value
- Portfolio Tracking: Monitor token distribution patterns and concentration levels over time
- Historical Analysis: Analyze token holder behavior and balance changes for research and investment decisions
- Liquidity Assessment: Understand how token ownership has evolved to assess market dynamics
- Risk Management: Track large holder movements and concentration risks for better portfolio management
- Market Intelligence: Gain insights into token adoption and distribution patterns for competitive analysis
Endpoint Details
URL:
https://api.cambrian.org/solana/tokens/holders-over-time
Method: GET
Authentication: Required via X-API-Key header
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| token_address | string | Yes | - | The program ID (mint address) of the token. |
| interval | integer | Yes | - | Block interval for sampling balances. |
| start_block | integer | Yes | - | Starting block number for the time range. |
| end_block | integer | Yes | - | Ending block number for the time range. |
Response Field Descriptions
| Response Field | Type | Description |
|---|---|---|
| blockNumber | UInt64 | Block number at which this holder balance snapshot was recorded. |
| blockTime | DateTime('UTC') | UTC timestamp corresponding to blockNumber. |
| account | FixedString(44) | Solana account address holding the token. |
| balanceUi | Float64 | Human-readable token balance, adjusted for the token's decimals. |
| balanceRaw | UInt64 | Raw token balance in the smallest base unit (unadjusted for decimals). |
Examples
1. Snapshot Token Holders Over a Block Range
Fetch holder balance snapshots for a specific SPL token across a 200,000-block range, sampled every 100,000 blocks.
curl -X GET "https://api.cambrian.org/solana/tokens/holders-over-time?token_address=27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4&interval=100000&start_block=395800000&end_block=396000000" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json"
Response:
[
{
"columns": [
{
"name": "blockNumber",
"type": "UInt64"
},
{
"name": "blockTime",
"type": "DateTime('UTC')"
},
{
"name": "account",
"type": "FixedString(44)"
},
{
"name": "balanceUi",
"type": "Float64"
},
{
"name": "balanceRaw",
"type": "UInt64"
}
],
"data": [
[
395900000,
"2026-01-25T19:42:16+00:00",
"AgnTi2m37HvVqNbcEzWmooxfRFAVKTo9QZ6NHvJjitew",
49639.912345,
49639912345
],
[
395900000,
"2026-01-25T19:42:16+00:00",
"mVpNmozxcJxpEtSrjcpuREqFkcVVdqGXg4GdJpHvRVp",
3606.174917,
3606174917
],
[
395900000,
"2026-01-25T19:42:16+00:00",
"7beNLayHpdpqNsHhxWnzCkHoN9ASTcMHZoA6yVgkKMSo",
403.502152,
403502152
],
[
395900000,
"2026-01-25T19:42:16+00:00",
"AqD36cHuHeGzNK3AKnn9Sy1uKfRkgs94BG29c5aR5fQ",
125.544764,
125544764
],
[
395900000,
"2026-01-25T19:42:16+00:00",
"8b56iWZqVk15KjcDmcQctUBauHZ5kdhYHXBDxdGqvTn4",
110.984518,
110984518
],
[
395900000,
"2026-01-25T19:42:16+00:00",
"6wh6ymEMEHhx8WmS4LH2RHJM7xGQtN7YZBFQmxpSny7c",
49.218273,
49218273
],
[
395900000,
"2026-01-25T19:42:16+00:00",
"BoEz8VsJtvywEedFYpAveLFRS31i4gBzyB9NPsndgS99",
45.241709,
45241709
],
[
395900000,
"2026-01-25T19:42:16+00:00",
"3xvGv3B8MDbN2hBX25NWSyfTKJTjLoULZU21A42wF2Z7",
17.774227,
17774227
],
[
395900000,
"2026-01-25T19:42:16+00:00",
"FiDAd4pi6jN47QTHdbsaYzBCJwUikYiYSm2LZFXpD3u9",
10.296345,
10296345
],
[
395900000,
"2026-01-25T19:42:16+00:00",
"CGJKkJe1UdBxfnHRES65zuNhEeM9aFnXh1gJG8RZegLE",
2.680754,
2680754
]
],
"rows": 338
}
]
Result collections are limited to 10 items per response. The rows field (338) reflects the total number of matching holder-snapshot records for the requested block range, while data contains only the first 10, all from block 395900000 sorted by balance descending.
x402 Payment Option
This endpoint supports pay-per-use access via the x402 payment protocol (v2): pay $0.05 USDC per request using blockchain micropayments. No API key required.
Quick Start (TypeScript)
npm install @x402/fetch @x402/evm viem
import { x402Client } from "@x402/core/client";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { wrapFetchWithPayment } from "@x402/fetch";
import { privateKeyToAccount } from "viem/accounts";
const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);
const client = new x402Client();
client.register("eip155:*", new ExactEvmScheme(signer));
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
const response = await fetchWithPayment(
"https://x402.cambrian.org/solana/tokens/holders-over-time"
);
const data = await response.json();
Quick Start (Python)
pip install "x402[httpx]"
import asyncio, os
from eth_account import Account
from x402 import x402Client
from x402.http.clients import x402HttpxClient
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client
async def main():
client = x402Client()
account = Account.from_key(os.getenv("EVM_PRIVATE_KEY"))
register_exact_evm_client(client, EthAccountSigner(account))
async with x402HttpxClient(client) as http:
response = await http.get("https://x402.cambrian.org/solana/tokens/holders-over-time")
print(response.json())
asyncio.run(main())
Payment Flow
- Send a normal request to the endpoint (no API key needed)
- Server returns
402 Payment Requiredwith payment details - The x402 SDK automatically signs a payment authorization with your wallet
- The SDK resubmits the request with the signed payment
- Server verifies payment and returns the API response
The x402 SDK handles steps 2-5 automatically.
Network: Base (chain ID 8453) | Currency: USDC | Price: $0.05 per request