Fetch human-readable transaction history for any Solana address with filtering, time and slot ranges, and pagination.
The Enhanced Transactions API is a legacy product in maintenance mode. It still works and these pages remain available, but it is not receiving new parser types or feature work. For new builds, use getTransactionsForAddress for transaction history and backfill, and the Wallet API for human-readable wallet data.
The Transaction History endpoint returns human-readable transaction history for any Solana address. Instead of dealing with raw instruction data and account lists, you get structured information about:
What happened in the transaction (transfers, swaps, NFT activities).
Which accounts were involved.
How much SOL or how many tokens were transferred.
Associated metadata (token mint addresses, token names, token symbols, and more).
Send a GET request to /v0/addresses/{address}/transactions. Under the hood, this endpoint is powered by the getTransactionsForAddress RPC method.
On Solana, a wallet doesn’t hold tokens directly. Instead, the wallet owns token accounts, and those token accounts hold the tokens. When someone sends you USDC, it goes to your USDC token account rather than your main wallet address.This endpoint is unique because it can query a wallet’s complete token history, including associated token accounts (ATAs). Native RPC methods such as getSignaturesForAddress do not include ATAs.The token-accounts filter controls this behavior:
none (default) — only returns transactions that directly reference the wallet address. Use this when you only care about direct wallet interactions.
balanceChanged (recommended) — returns transactions that reference the wallet address or modify the balance of a token account owned by the wallet. This filters out spam and unrelated operations like fee collections or delegations, giving you a clean view of meaningful wallet activity.
all — returns all transactions that reference the wallet address or any token account owned by the wallet.
The token-accounts filter relies on the owner field in token balance metadata, which was not available before slot 111,491,819 (~December 2022). Transactions involving token accounts active before this slot may be missing from balanceChanged and all results. See the getTransactionsForAddress tutorial for a workaround with a full code example.
Type filtering happens at runtime: the API searches transactions sequentially until it finds at least 50 matching items. If it cannot find any matches within the search window, it returns an error with a signature to continue the search from. This is expected behavior, not a failure.
When no matching transactions are found within the current search window, the API returns an error response like this:
{ "error": "Failed to find events within the search period. To continue search, query the API again with the `before-signature` parameter set to 2UKbsu95YzxGjUGYRg2znozmmVADVgmnhHqzDxq8Xfb3V5bf2NHUkaXGPrUpQnRFVHVKbawdQXtm4xJt9njMDHvg."}
To continue, use the signature from the error message with the appropriate parameter (before-signature for descending, after-signature for ascending) on your next request.
Continuation loop for type filters (full example)
const fetchFilteredTransactions = async (sortOrder = 'desc') => { const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K"; const transactionType = "NFT_SALE"; let continuationSignature = null; let allFilteredTransactions = []; let maxRetries = 10; // Prevent infinite loops let retryCount = 0; // Determine which parameter to use based on sort order const continuationParam = sortOrder === 'asc' ? 'after-signature' : 'before-signature'; while (retryCount < maxRetries) { // Build URL with optional continuation parameter let url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&type=${transactionType}&sort-order=${sortOrder}`; if (continuationSignature) { url += `&${continuationParam}=${continuationSignature}`; } try { const response = await fetch(url); const data = await response.json(); // Check if we received an error about search period if (data.error && data.error.includes("Failed to find events within the search period")) { // Extract the signature from the error message const signatureMatch = data.error.match(/parameter set to ([A-Za-z0-9]+)/); if (signatureMatch && signatureMatch[1]) { console.log(`No results in this period. Continuing search from: ${signatureMatch[1]}`); continuationSignature = signatureMatch[1]; retryCount++; continue; // Continue searching with new signature } else { console.log("No more transactions to search"); break; } } // Check if we received transactions if (Array.isArray(data) && data.length > 0) { console.log(`Found ${data.length} ${transactionType} transactions`); allFilteredTransactions = [...allFilteredTransactions, ...data]; // Set continuation signature for next page continuationSignature = data[data.length - 1].signature; retryCount = 0; // Reset retry count since we found results } else { console.log("No more transactions found"); break; } } catch (error) { console.error("Error fetching transactions:", error); break; } } console.log(`Total ${transactionType} transactions found: ${allFilteredTransactions.length}`); return allFilteredTransactions;};// Usage examples:// Descending order (newest first) - uses 'before-signature' parameterfetchFilteredTransactions('desc');// Ascending order (oldest first) - uses 'after-signature' parameterfetchFilteredTransactions('asc');
Key points:
The API searches through up to 50 transactions at a time when using type filters.
If no matches are found, use the signature from the error message to continue searching.
Use before-signature when searching in descending order (default, newest first).
Use after-signature when searching in ascending order (oldest first) — required for chronological searches.
Implement a maximum retry limit to prevent infinite loops.