> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Transaction History

> Fetch human-readable transaction history for any Solana address with filtering, time and slot ranges, and pagination.

<Warning>
  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`](/rpc/gettransactionsforaddress) for transaction history and backfill, and the [Wallet API](/wallet-api/overview) for human-readable wallet data.
</Warning>

## Overview

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/gettransactionsforaddress) RPC method.

## When to use this

* You are displaying an address's transaction history to users (wallets, portfolio trackers, explorers).
* You want pre-parsed, human-readable history without writing your own decoder.
* You need to filter history by transaction type, time range, or slot range.
* You need a wallet's complete token history, including associated token accounts (ATAs) — see below.

For new builds, [`getTransactionsForAddress`](/rpc/gettransactionsforaddress) is the modern, Helius-native path with server-side filtering and token-account lookups.

## Quickstart

<Steps>
  <Step title="Get your API key">
    Sign up at [dashboard.helius.dev](https://dashboard.helius.dev) and copy your API key.
  </Step>

  <Step title="GET the address transactions endpoint">
    Retrieve transaction history for any Solana address.

    <Tabs>
      <Tab title="JavaScript">
        ```javascript theme={"system"}
        const fetchWalletTransactions = async () => {
          const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K"; // Replace with target wallet
          const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY`;

          const response = await fetch(url);
          const transactions = await response.json();
          console.log("Wallet transactions:", transactions);
        };

        fetchWalletTransactions();
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={"system"}
        import requests

        def fetch_wallet_transactions():
            wallet_address = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K"  # Replace with target wallet
            url = f"https://mainnet.helius-rpc.com/v0/addresses/{wallet_address}/transactions?api-key=YOUR_API_KEY"

            response = requests.get(url)
            transactions = response.json()
            print("Wallet transactions:", transactions)

        fetch_wallet_transactions()
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Filter and paginate">
    Narrow results with the `type`, time, and slot filters below, then page through high-volume addresses with signature cursors.
  </Step>
</Steps>

## Network support

| Network | Supported | Retention period |
| ------- | --------- | ---------------- |
| Mainnet | Yes       | Unlimited        |
| Devnet  | Yes       | 2 weeks          |
| Testnet | No        | N/A              |

## Request parameters

| Parameter          | Description                                                           | Default     | Example                          |
| ------------------ | --------------------------------------------------------------------- | ----------- | -------------------------------- |
| `limit`            | Number of transactions to return (1-100)                              | 10          | `&limit=25`                      |
| `before-signature` | Fetch transactions before this signature (use with `sort-order=desc`) | -           | `&before-signature=sig123...`    |
| `after-signature`  | Fetch transactions after this signature (use with `sort-order=asc`)   | -           | `&after-signature=sig456...`     |
| `type`             | Filter by transaction type                                            | -           | `&type=NFT_SALE`                 |
| `sort-order`       | Sort order for results                                                | `desc`      | `&sort-order=asc`                |
| `token-accounts`   | Filter transactions for related token accounts                        | `none`      | `&token-accounts=balanceChanged` |
| `commitment`       | Commitment level                                                      | `finalized` | `&commitment=confirmed`          |

### Time-based filtering

| Parameter  | Description                                   | Example                |
| ---------- | --------------------------------------------- | ---------------------- |
| `gt-time`  | Transactions after this Unix timestamp        | `&gt-time=1656442333`  |
| `gte-time` | Transactions at or after this Unix timestamp  | `&gte-time=1656442333` |
| `lt-time`  | Transactions before this Unix timestamp       | `&lt-time=1656442333`  |
| `lte-time` | Transactions at or before this Unix timestamp | `&lte-time=1656442333` |

### Slot-based filtering

| Parameter  | Description                         | Example               |
| ---------- | ----------------------------------- | --------------------- |
| `gt-slot`  | Transactions after this slot        | `&gt-slot=148277128`  |
| `gte-slot` | Transactions at or after this slot  | `&gte-slot=148277128` |
| `lt-slot`  | Transactions before this slot       | `&lt-slot=148277128`  |
| `lte-slot` | Transactions at or before this slot | `&lte-slot=148277128` |

Filtering notes:

* Time parameters use Unix timestamps (seconds since epoch); slot parameters use Solana slot numbers.
* You cannot combine time-based and slot-based filters in the same request.
* Use `sort-order=asc` for ascending (oldest first) or `sort-order=desc` for descending (newest first).
* Use time or slot filters to reduce the search space when you know the approximate period, and pair them with `limit` to control page size.

## Associated token accounts

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.

<Warning>
  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](/rpc/gettransactionsforaddress#limitations-and-edge-cases) for a workaround with a full code example.
</Warning>

## Filters

### Filter by transaction type

Get only specific transaction types, such as NFT sales, token transfers, or swaps:

<Tabs>
  <Tab title="NFT Sales">
    ```javascript theme={"system"}
    const fetchNftSales = async () => {
      const tokenAddress = "GjUG1BATg5V4bdAr1csKys1XK9fmrbntgb1iV7rAkn94"; // NFT mint address
      const url = `https://mainnet.helius-rpc.com/v0/addresses/${tokenAddress}/transactions?api-key=YOUR_API_KEY&type=NFT_SALE`;

      const response = await fetch(url);
      const nftSales = await response.json();
      console.log("NFT sale transactions:", nftSales);
    };
    ```
  </Tab>

  <Tab title="Token Transfers">
    ```javascript theme={"system"}
    const fetchTokenTransfers = async () => {
      const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K"; // Wallet address
      const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&type=TRANSFER`;

      const response = await fetch(url);
      const transfers = await response.json();
      console.log("Transfer transactions:", transfers);
    };
    ```
  </Tab>

  <Tab title="Swaps">
    ```javascript theme={"system"}
    const fetchSwapTransactions = async () => {
      const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K"; // Wallet address
      const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&type=SWAP`;

      const response = await fetch(url);
      const swaps = await response.json();
      console.log("Swap transactions:", swaps);
    };
    ```
  </Tab>
</Tabs>

For the full list of supported transaction types, see the [Transaction History API reference](/api-reference/enhanced-transactions/gettransactionsbyaddress).

### Runtime type filtering

<Note>
  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.
</Note>

When no matching transactions are found within the current search window, the API returns an error response like this:

```json theme={"system"}
{
  "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.

<Accordion title="Continuation loop for type filters (full example)">
  ```javascript theme={"system"}
  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' parameter
  fetchFilteredTransactions('desc');

  // Ascending order (oldest first) - uses 'after-signature' parameter
  fetchFilteredTransactions('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.
</Accordion>

## Examples

The following scenarios cover time and slot ranges, sort order, ATAs, and combined filters.

<Accordion title="Filter by time range">
  Get transactions within a specific time window:

  <Tabs>
    <Tab title="Last 24 Hours">
      ```javascript theme={"system"}
      const fetchRecentTransactions = async () => {
        const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";
        const now = Math.floor(Date.now() / 1000);
        const oneDayAgo = now - (24 * 60 * 60);

        const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&gte-time=${oneDayAgo}&lte-time=${now}`;

        const response = await fetch(url);
        const transactions = await response.json();
        console.log("Transactions from last 24 hours:", transactions);
      };
      ```
    </Tab>

    <Tab title="Specific Date Range">
      ```javascript theme={"system"}
      const fetchTransactionsByDateRange = async () => {
        const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";

        // January 1, 2024 to January 31, 2024
        const startTime = Math.floor(new Date('2024-01-01').getTime() / 1000);
        const endTime = Math.floor(new Date('2024-01-31').getTime() / 1000);

        const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&gte-time=${startTime}&lte-time=${endTime}`;

        const response = await fetch(url);
        const transactions = await response.json();
        console.log("Transactions in January 2024:", transactions);
      };
      ```
    </Tab>
  </Tabs>
</Accordion>

<Accordion title="Filter by slot range">
  Get transactions within a specific slot range:

  ```javascript theme={"system"}
  const fetchTransactionsBySlotRange = async () => {
    const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";
    const startSlot = 148000000;
    const endSlot = 148100000;

    const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&gte-slot=${startSlot}&lte-slot=${endSlot}`;

    const response = await fetch(url);
    const transactions = await response.json();
    console.log(`Transactions between slots ${startSlot} and ${endSlot}:`, transactions);
  };
  ```
</Accordion>

<Accordion title="Change sort order">
  Get transactions in ascending order (oldest first):

  ```javascript theme={"system"}
  const fetchOldestTransactions = async () => {
    const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";
    const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&sort-order=asc&limit=10`;

    const response = await fetch(url);
    const transactions = await response.json();
    console.log("10 oldest transactions:", transactions);
  };
  ```
</Accordion>

<Accordion title="Include transfers for related token accounts">
  Query a wallet's full history, including associated token addresses (ATAs):

  ```javascript theme={"system"}
  const fetchTransactionsWithATA = async () => {
    const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";

    const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&token-accounts=balanceChanged&sort-order=desc&limit=50`;

    const response = await fetch(url);
    const transactions = await response.json();
    console.log("Most recent transactions (including ATA transfers)", transactions);
  };
  ```
</Accordion>

<Accordion title="Combine multiple filters">
  Combine type filtering with a time range and custom sort order:

  ```javascript theme={"system"}
  const fetchFilteredTransactionsAdvanced = async () => {
    const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";

    // Get NFT sales from the last 7 days, oldest first
    const now = Math.floor(Date.now() / 1000);
    const sevenDaysAgo = now - (7 * 24 * 60 * 60);

    const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&type=NFT_SALE&gte-time=${sevenDaysAgo}&sort-order=asc&limit=50`;

    const response = await fetch(url);
    const transactions = await response.json();
    console.log("NFT sales from last 7 days (oldest first):", transactions);
  };
  ```
</Accordion>

## Pagination

For high-volume addresses, page through results using the last signature in each batch as the cursor:

```javascript theme={"system"}
const fetchAllTransactions = async () => {
  const walletAddress = "2k5AXX4guW9XwRQ1AKCpAuUqgWDpQpwFfpVFh3hnm2Ha"; // Replace with target wallet
  const baseUrl = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY`;
  let url = baseUrl;
  let lastSignature = null;
  let allTransactions = [];

  while (true) {
    if (lastSignature) {
      url = baseUrl + `&before-signature=${lastSignature}`;
    }

    const response = await fetch(url);

    // Check response status
    if (!response.ok) {
      console.error(`API error: ${response.status}`);
      break;
    }

    const transactions = await response.json();

    if (transactions && transactions.length > 0) {
      console.log(`Fetched batch of ${transactions.length} transactions`);
      allTransactions = [...allTransactions, ...transactions];
      lastSignature = transactions[transactions.length - 1].signature;
    } else {
      console.log(`Finished! Total transactions: ${allTransactions.length}`);
      break;
    }
  }

  return allTransactions;
};
```

To paginate within a time range, keep the time filters on every request and advance the `before-signature` cursor each loop:

```javascript theme={"system"}
const fetchAllTransactionsInTimeRange = async () => {
  const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";
  const startTime = Math.floor(new Date('2024-01-01').getTime() / 1000);
  const endTime = Math.floor(new Date('2024-01-31').getTime() / 1000);

  let beforeSignature = null;
  let allTransactions = [];

  while (true) {
    let url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&gte-time=${startTime}&lte-time=${endTime}&limit=100`;

    if (beforeSignature) {
      url += `&before-signature=${beforeSignature}`;
    }

    const response = await fetch(url);
    const transactions = await response.json();

    if (!Array.isArray(transactions) || transactions.length === 0) {
      break;
    }

    allTransactions = [...allTransactions, ...transactions];
    beforeSignature = transactions[transactions.length - 1].signature;

    console.log(`Fetched ${transactions.length} transactions, total: ${allTransactions.length}`);
  }

  console.log(`Total transactions in time range: ${allTransactions.length}`);
  return allTransactions;
};
```

## Next steps

<CardGroup cols={2}>
  <Card title="getTransactionsForAddress" icon="clock-rotate-left" href="/rpc/gettransactionsforaddress">
    The modern, Helius-native replacement for transaction history and backfill.
  </Card>

  <Card title="Wallet API" icon="wallet" href="/wallet-api/overview">
    REST endpoints for human-readable wallet data: balances, history, and transfers.
  </Card>

  <Card title="Parse Transactions" icon="code" href="/enhanced-transactions/parse-transactions">
    Parse one or more transaction signatures into human-readable data.
  </Card>

  <Card title="Getting Data overview" icon="database" href="/getting-data">
    Compare every Helius option for querying Solana data.
  </Card>
</CardGroup>
