Data API
GET /v1/wallets/{wallet}/holdings
A wallet's token holdings (portfolio) across all tracked tokens, priced. The self-hosted getTokenAccountsByOwner equivalent.
Endpoint
GET https://solindex.infinityblocks.io/v1/wallets/{wallet}/holdings
Authentication
Send your key in the x-api-key header (or ?api-key=). See Authentication.
Path parameters
| Param | Description |
|---|---|
wallet | Base-58 wallet address. |
Query parameters
| Param | Type | Default | Allowed / range |
|---|---|---|---|
limit | int | 50 | 1–500 (page size) |
offset | int | 0 | Rows to skip |
page | int | — | 1-based page (alternative to offset) |
minUsd | float | 0 | Drop holdings worth less than this USD value (0 = all) |
sort | string | value | value (valueUsd desc — portfolio view) or mint (stable mint order — for exports) |
after | mint | — | Keyset cursor: return holdings with mint > this value, in mint order. Implies sort=mint; ignores offset. Use page.nextCursor to continue. |
Request
curl -s "https://solindex.infinityblocks.io/v1/wallets/<WALLET>/holdings?minUsd=1" \
-H "x-api-key: <API_KEY>"
const r = await fetch("https://solindex.infinityblocks.io/v1/wallets/<WALLET>/holdings?minUsd=1", {
headers: { "x-api-key": "<API_KEY>" },
});
const { data } = await r.json();
Response
{ "data": {
"count": 5, "totalValueUsd": 101.13,
"holdings": [
{ "mint": "EPjFW…Dt1v", "symbol": "USDC", "name": "USD Coin",
"decimals": 6, "balance": 100.724535, "priceUsd": 1, "valueUsd": 100.72 },
{ "mint": "Df6y…pump", "symbol": "CHILLGUY", "name": "Just a chill guy",
"decimals": 6, "balance": 39.638425, "priceUsd": 0.00962, "valueUsd": 0.38 },
… ] },
"page": { "limit": 50, "offset": 0, "total": 5, "returned": 5, "hasMore": false, "nextOffset": null } }
The self-hosted equivalent of
Freshness & consistency. Balances come from the live geyser token-account change stream and are written in ~1-second batches; prices are maintained per-mint from the latest trade, also within ~1 second. A holding’s
Completeness semantics. Zero-balance accounts are omitted (only balances > 0 are returned). Ordering is deterministic —
getTokenAccountsByOwner for our scope — a wallet's holdings across every tracked token (DegenSafe launches + Raydium-traded tokens), each priced from the latest trade with a computed valueUsd; sorted by value, with a portfolio totalValueUsd. Use ?minUsd= to hide dust.Freshness & consistency. Balances come from the live geyser token-account change stream and are written in ~1-second batches; prices are maintained per-mint from the latest trade, also within ~1 second. A holding’s
priceUsd/valueUsd can therefore trail an actively-trading token by up to a second between repeated calls; balances and the mint set are stable. The endpoint is served from wallet-keyed structures, so response cost is bounded by the wallet’s own holdings — page limit bounds output work, and high-cardinality wallets (thousands of mints) are fully supported.Completeness semantics. Zero-balance accounts are omitted (only balances > 0 are returned). Ordering is deterministic —
valueUsd desc, then balance desc, then mint asc. For complete exports, use cursor pagination: pass ?sort=mint and follow page.nextCursor with ?after=<mint> until it is null — the mint key is immutable, so the sweep is duplicate-free and complete (exactly data.count holdings) even while prices move. Plain offset pagination over the default value ordering is a live view: a price tick between page fetches can re-rank rows across a page boundary (a holding may repeat or be missed) — fine for showing top-of-portfolio pages, wrong for exhaustive enumeration. Scope note: tracked tokens only — a wallet's holdings of tokens we don't index (arbitrary all-SPL) are not included. During a (rare, alerted) indexer outage, balances reflect stream state as of the outage start and catch up automatically on recovery.Try it
Run GET /v1/wallets/{wallet}/holdingslive · GET
Your key is stored only in this browser (localStorage).
—