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

# Transactions

> Query transaction history with powerful filtering and search

Retrieve paginated transaction history for blockchain addresses with comprehensive filtering, full-text search, and detailed transaction data.

<Info>
  **Cost:** 1 credit per call
</Info>

<Warning>
  **Index Limit** — Addresses with more than 100,000 transactions are not automatically indexed. Contact support for assistance with large addresses.
</Warning>

<Note>
  **Interactive Playground:** Test this endpoint in the [API Playground](/api-reference/transactions). Get your API key at [data.octav.fi](https://data.octav.fi/)
</Note>

***

## Endpoint

<CodeGroup>
  ```bash Request theme={null}
  GET https://api.octav.fi/v1/transactions
  ```

  ```bash Example theme={null}
  curl -X GET "https://api.octav.fi/v1/transactions?addresses=0x6426af179aabebe47666f345d69fd9079673f6cd&limit=10&offset=0&sort=DESC" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```
</CodeGroup>

***

## Required Parameters

<ParamField query="addresses" type="string" required>
  Wallet address (EVM / SOL)

  ```
  addresses=0x6426af179aabebe47666f345d69fd9079673f6cd
  ```
</ParamField>

<ParamField query="limit" type="integer" required>
  Number of transactions per page

  * **Minimum:** 1
  * **Maximum:** 250
  * **Recommended:** 10-50 for optimal performance
</ParamField>

<ParamField query="offset" type="integer" required>
  Pagination offset (0-based)

  ```
  offset=0   # First page
  offset=10  # Second page (if limit=10)
  offset=20  # Third page (if limit=10)
  ```
</ParamField>

***

## Optional Parameters

### Search & Filter

<ParamField query="initialSearchText" type="string">
  Full-text search in transaction assets
  Searches across:

  * Token symbols
  * Token names
  * Contract addresses
  * Transaction descriptions

  ```
  initialSearchText=USDC
  ```
</ParamField>

<ParamField query="interactingAddresses" type="string">
  Filter by interacting addresses (comma-separated)
  Shows only transactions where these addresses are involved:

  ```
  interactingAddresses=0x123...,0x456...
  ```
</ParamField>

<ParamField query="networks" type="string">
  Filter by blockchain networks (comma-separated chain keys)

  ```
  networks=ethereum,arbitrum,base
  ```

  See [Supported Blockchains](/docs/supported-blockchains) for chain keys
</ParamField>

<ParamField query="txTypes" type="string">
  Filter by transaction types (comma-separated type keys)

  See [Transaction Types](https://octav-0131e508.mintlify.app/api/reference/transaction-types)

  Common types:

  * `SEND` - Token transfers out
  * `RECEIVE` - Token transfers in
  * `SWAP` - Token swaps
  * `DEPOSIT` - DeFi deposits
  * `WITHDRAW` - DeFi withdrawals
  * `STAKE` - Staking operations
  * `CLAIM` - Reward claims
  * `APPROVE` - Token approvals

  ```
  txTypes=SWAP,DEPOSIT
  ```
</ParamField>

<ParamField query="protocols" type="string">
  Filter by protocol keys (comma-separated)

  See [Protocol Keys](https://protocols.octav.fi/)

  ```
  protocols=uniswap_v3,aave_v3
  ```
</ParamField>

<ParamField query="hideSpam" type="boolean" default="false">
  Exclude spam transactions

  ```
  hideSpam=true
  ```
</ParamField>

<ParamField query="hideDust" type="boolean" default="false">
  Exclude dust transactions

  ```
  hideDust=true
  ```
</ParamField>

### Sorting & Date Range

<ParamField query="sort" type="string" default="DESC">
  Sort order by timestamp

  * `DESC` - Newest first (recommended)
  * `ASC` - Oldest first

  ```
  sort=DESC
  ```
</ParamField>

<ParamField query="startDate" type="string">
  Start of the date range, ISO 8601. Inclusive — filters `timestamp >= startDate` at the exact instant you pass, compared in UTC.

  Use camelCase; `start_date` is rejected with a 400 validation error. Omit to start from the wallet's first indexed transaction.

  ```
  startDate=2024-01-01T00:00:00Z
  ```
</ParamField>

<ParamField query="endDate" type="string">
  End of the date range, ISO 8601. Inclusive, but **rounded up to the end of that UTC calendar day** (`23:59:59Z`) — the time-of-day you send is ignored. Filters `timestamp <= endOfDay(endDate)`.

  Use camelCase; `end_date` is rejected with a 400 validation error. Omit to include transactions up to the present.

  ```
  endDate=2024-12-31T23:59:59Z
  ```
</ParamField>

<Warning>
  **Building daily windows without duplicates** — because `endDate` rounds up to the end of its UTC calendar day:

  * **Single day:** set `startDate` and `endDate` to the same date (e.g. `startDate=2026-05-27&endDate=2026-05-27` returns `2026-05-27 00:00:00Z`–`23:59:59Z`).
  * **Range:** set `startDate` to the first day and `endDate` to the last day you want included.
  * **Do not** set `endDate` to the next day's midnight (e.g. `2026-05-28T00:00:00Z`) — it rounds up to the end of the 28th and pulls in an extra day, so the same transaction appears in two consecutive windows.

  Since `timestamp` is integer epoch seconds, contiguous same-day windows have no overlap and no gap.
</Warning>

### NFT Filters

<ParamField query="tokenId" type="string">
  Filter by NFT token ID

  ```
  tokenId=1234
  ```
</ParamField>

***

## Response

The response is an object with a single `transactions` key holding the array:

```json theme={null}
{ "transactions": [ { /* ...tx... */ } ] }
```

### Transaction Object

<ResponseField name="hash" type="string">
  Transaction hash
</ResponseField>

<ResponseField name="timestamp" type="string">
  Transaction timestamp in seconds since epoch
</ResponseField>

<ResponseField name="chain" type="object">
  Blockchain information

  * `key`: Chain identifier
  * `name`: Chain display name
</ResponseField>

<ResponseField name="from" type="string">
  Address initiating the transaction
</ResponseField>

<ResponseField name="to" type="string">
  Recipient address
</ResponseField>

<ResponseField name="type" type="string">
  Transaction type (DEPOSIT, WITHDRAWAL, SWAP, etc.)
</ResponseField>

<ResponseField name="protocol" type="object">
  Protocol information (if applicable)

  * `key`: Protocol identifier
  * `name`: Protocol display name
</ResponseField>

<ResponseField name="subProtocol" type="object">
  Sub-protocol information (if applicable)

  * `key`: Sub-protocol identifier
  * `name`: Sub-protocol name
</ResponseField>

<ResponseField name="value" type="string">
  Transaction value in native asset
</ResponseField>

<ResponseField name="valueFiat" type="string">
  Transaction value in USD
</ResponseField>

<ResponseField name="fees" type="string">
  Fees paid in native asset
</ResponseField>

<ResponseField name="feesFiat" type="string">
  Fees paid in USD
</ResponseField>

<ResponseField name="assetsIn" type="Asset[]">
  Assets received in the transaction.

  Each asset contains `symbol`, `name`, `balance`, `value`, `decimal`, `contract`, `chainKey`, and `chainContract`. The token quantity is `balance` (not `amount`), and the on-chain address is `contract` (not `contractAddress`); native assets use the zero address. There is no nested `chain` object at the asset level — use `chainKey` / `chainContract`.
</ResponseField>

<ResponseField name="assetsOut" type="Asset[]">
  Assets sent out in the transaction. Same shape as `assetsIn`.
</ResponseField>

<ResponseField name="functionName" type="string">
  Smart contract function called
</ResponseField>

<ResponseField name="closedPnl" type="string">
  Realized profit/loss for the transaction (if available, otherwise "N/A")
</ResponseField>

<ResponseField name="nativeAssetFees" type="object">
  Detailed fee breakdown
</ResponseField>

***

## Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.octav.fi/v1/transactions?addresses=0x6426af179aabebe47666f345d69fd9079673f6cd&limit=10&offset=0&sort=DESC&hideSpam=true" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  const params = new URLSearchParams({
    addresses: '0x6426af179aabebe47666f345d69fd9079673f6cd',
    limit: '10',
    offset: '0',
    sort: 'DESC',
    hideSpam: 'true'
  });
  const response = await fetch(
    `https://api.octav.fi/v1/transactions?${params}`,
    {
      headers: {
        'Authorization': `Bearer ${apiKey}`
      }
    }
  );
  const { transactions } = await response.json();
  console.log(`Retrieved ${transactions.length} transactions`);
  ```

  ```python Python theme={null}
  import requests
  params = {
      'addresses': '0x6426af179aabebe47666f345d69fd9079673f6cd',
      'limit': 10,
      'offset': 0,
      'sort': 'DESC',
      'hideSpam': True
  }
  response = requests.get(
      'https://api.octav.fi/v1/transactions',
      params=params,
      headers={'Authorization': f'Bearer {api_key}'}
  )
  transactions = response.json()['transactions']
  print(f'Retrieved {len(transactions)} transactions')
  ```

  ```typescript TypeScript theme={null}
  interface Asset {
    symbol: string;
    name: string;
    balance: string;
    value: string;
    decimal: string;
    contract: string;
    chainKey: string;
    chainContract: string;
  }
  interface Transaction {
    hash: string;
    timestamp: string;
    chain: {
      key: string;
      name: string;
    };
    from: string;
    to: string;
    type: string;
    value: string;
    valueFiat: string;
    fees: string;
    feesFiat: string;
    assetsIn: Asset[];
    assetsOut: Asset[];
    protocol?: {
      key: string;
      name: string;
    };
  }
  interface TransactionsResponse {
    transactions: Transaction[];
  }
  const params = new URLSearchParams({
    addresses: '0x6426af179aabebe47666f345d69fd9079673f6cd',
    limit: '10',
    offset: '0',
    sort: 'DESC',
    hideSpam: 'true'
  });
  const response = await fetch(
    `https://api.octav.fi/v1/transactions?${params}`,
    {
      headers: {
        'Authorization': `Bearer ${apiKey}`
      }
    }
  );
  const { transactions }: TransactionsResponse = await response.json();
  console.log(`Retrieved ${transactions.length} transactions`);
  ```
</CodeGroup>

***

## Example Response

<Accordion title="View Full Response" icon="code">
  ```json theme={null}
  {
    "transactions": [
      {
        "hash": "0xa1b2c3d4e5f6...",
        "timestamp": "1699012800",
        "chain": {
          "key": "ethereum",
          "name": "Ethereum"
        },
        "from": "0x6426af179aabebe47666f345d69fd9079673f6cd",
        "to": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
        "type": "SWAP",
        "protocol": {
          "key": "uniswap_v3",
          "name": "Uniswap V3"
        },
        "value": "0",
        "valueFiat": "0",
        "fees": "0.002134",
        "feesFiat": "7.12",
        "assetsIn": [
          {
            "symbol": "weth",
            "name": "wrapped ether",
            "balance": "1.5",
            "value": "4800.00",
            "decimal": "18",
            "contract": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
            "chainKey": "ethereum",
            "chainContract": "ethereum:0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
          }
        ],
        "assetsOut": [
          {
            "symbol": "usdc",
            "name": "usd coin",
            "balance": "4795.23",
            "value": "4795.23",
            "decimal": "6",
            "contract": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
            "chainKey": "ethereum",
            "chainContract": "ethereum:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
          }
        ],
        "functionName": "swapExactTokensForTokens",
        "nativeAssetFees": {
          "symbol": "eth",
          "balance": "0.002134",
          "value": "7.12",
          "contract": "0x0000000000000000000000000000000000000000",
          "chainKey": "ethereum"
        }
      },
      {
        "hash": "0xf9e8d7c6b5a4...",
        "timestamp": "1698926400",
        "chain": {
          "key": "arbitrum",
          "name": "Arbitrum"
        },
        "from": "0x6426af179aabebe47666f345d69fd9079673f6cd",
        "to": "0x794a61358D6845594F94dc1DB02A252b5b4814aD",
        "type": "DEPOSIT",
        "protocol": {
          "key": "aave_v3",
          "name": "Aave V3"
        },
        "value": "0",
        "valueFiat": "0",
        "fees": "0.000421",
        "feesFiat": "1.35",
        "assetsIn": [],
        "assetsOut": [
          {
            "symbol": "usdc",
            "name": "usd coin",
            "balance": "10000",
            "value": "10000.00",
            "decimal": "6",
            "contract": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
            "chainKey": "arbitrum",
            "chainContract": "arbitrum:0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
          }
        ],
        "functionName": "supply",
        "nativeAssetFees": {
          "symbol": "eth",
          "balance": "0.000421",
          "value": "1.35",
          "contract": "0x0000000000000000000000000000000000000000",
          "chainKey": "arbitrum"
        }
      }
    ]
  }
  ```
</Accordion>

***

## Use Cases

<Tabs>
  <Tab title="Transaction History" icon="clock-rotate-left">
    Display transaction history with pagination:

    ```javascript theme={null}
    async function getTransactionHistory(address, page = 1, pageSize = 20) {
      const offset = (page - 1) * pageSize;
      const params = new URLSearchParams({
        addresses: address,
        limit: pageSize.toString(),
        offset: offset.toString(),
        sort: 'DESC',
        hideSpam: 'true'
      });
      const response = await fetch(
        `https://api.octav.fi/v1/transactions?${params}`,
        {
          headers: {
            'Authorization': `Bearer ${apiKey}`
          }
        }
      );
      const { transactions } = await response.json();
      return transactions;
    }
    // Get first page
    const page1 = await getTransactionHistory(address, 1);
    // Get next page
    const page2 = await getTransactionHistory(address, 2);
    ```
  </Tab>

  <Tab title="Filter by Type" icon="filter">
    Filter transactions by type:

    ```javascript theme={null}
    async function getSwapTransactions(address) {
      const params = new URLSearchParams({
        addresses: address,
        txTypes: 'SWAP',
        limit: '50',
        offset: '0',
        sort: 'DESC'
      });
      const response = await fetch(
        `https://api.octav.fi/v1/transactions?${params}`,
        {
          headers: {
            'Authorization': `Bearer ${apiKey}`
          }
        }
      );
      const { transactions } = await response.json();
      // Calculate total swap volume
      const totalVolume = transactions.reduce((sum, tx) => {
        return sum + parseFloat(tx.valueFiat || 0);
      }, 0);
      console.log(`Total swap volume: $${totalVolume}`);
      return transactions;
    }
    ```
  </Tab>

  <Tab title="Search Transactions" icon="magnifying-glass">
    Search for specific tokens or protocols:

    ```javascript theme={null}
    async function searchTransactions(address, searchTerm) {
      const params = new URLSearchParams({
        addresses: address,
        initialSearchText: searchTerm,
        limit: '50',
        offset: '0',
        sort: 'DESC'
      });
      const response = await fetch(
        `https://api.octav.fi/v1/transactions?${params}`,
        {
          headers: {
            'Authorization': `Bearer ${apiKey}`
          }
        }
      );
      const { transactions } = await response.json();
      return transactions;
    }
    // Search for USDC transactions
    const usdcTxs = await searchTransactions(address, 'USDC');
    // Search for Uniswap interactions
    const uniswapTxs = await searchTransactions(address, 'Uniswap');
    ```
  </Tab>

  <Tab title="Date Range Query" icon="calendar">
    Query transactions within a date range:

    ```javascript theme={null}
    async function getTransactionsInRange(address, startDate, endDate) {
      const params = new URLSearchParams({
        addresses: address,
        startDate: startDate.toISOString(),
        endDate: endDate.toISOString(),
        limit: '100',
        offset: '0',
        sort: 'DESC'
      });
      const response = await fetch(
        `https://api.octav.fi/v1/transactions?${params}`,
        {
          headers: {
            'Authorization': `Bearer ${apiKey}`
          }
        }
      );
      const { transactions } = await response.json();
      return transactions;
    }
    // Get last 30 days
    const endDate = new Date();
    const startDate = new Date();
    startDate.setDate(startDate.getDate() - 30);
    const recentTxs = await getTransactionsInRange(
      address,
      startDate,
      endDate
    );
    ```
  </Tab>

  <Tab title="Fee Analysis" icon="dollar-sign">
    Calculate total fees paid:

    ```javascript theme={null}
    async function calculateTotalFees(address, startDate, endDate) {
      let offset = 0;
      const limit = 250;
      let totalFees = 0;
      let hasMore = true;
      while (hasMore) {
        const params = new URLSearchParams({
          addresses: address,
          startDate: startDate.toISOString(),
          endDate: endDate.toISOString(),
          limit: limit.toString(),
          offset: offset.toString(),
          sort: 'DESC'
        });
        const response = await fetch(
          `https://api.octav.fi/v1/transactions?${params}`,
          {
            headers: {
              'Authorization': `Bearer ${apiKey}`
            }
          }
        );
        const { transactions } = await response.json();
        if (transactions.length === 0) {
          hasMore = false;
        } else {
          transactions.forEach(tx => {
            totalFees += parseFloat(tx.feesFiat || 0);
          });
          offset += limit;
          hasMore = transactions.length === limit;
        }
      }
      return totalFees;
    }
    const fees = await calculateTotalFees(address, startDate, endDate);
    console.log(`Total fees paid: $${fees.toFixed(2)}`);
    ```
  </Tab>
</Tabs>

***

## Pagination Best Practices

<AccordionGroup>
  <Accordion title="Efficient Pagination" icon="forward">
    **Use appropriate page sizes:**

    * Small pages (10-20): Fast response, more requests
    * Medium pages (50-100): Balanced approach (recommended)
    * Large pages (200-250): Fewer requests, slower response

    **Track pagination state:**

    ```javascript theme={null}
    class TransactionPaginator {
      constructor(address, pageSize = 50) {
        this.address = address;
        this.pageSize = pageSize;
        this.currentOffset = 0;
      }

      async nextPage() {
        const params = new URLSearchParams({
          addresses: this.address,
          limit: this.pageSize.toString(),
          offset: this.currentOffset.toString(),
          sort: 'DESC'
        });

        const response = await fetch(
          `https://api.octav.fi/v1/transactions?${params}`,
          {
            headers: {
              'Authorization': `Bearer ${apiKey}`
            }
          }
        );

        const { transactions } = await response.json();

        if (transactions.length > 0) {
          this.currentOffset += transactions.length;
        }

        return {
          transactions,
          hasMore: transactions.length === this.pageSize
        };
      }
    }
    ```
  </Accordion>

  <Accordion title="Handling Large Histories" icon="database">
    For addresses with many transactions:

    1. **Use filters to reduce results:**
       * Filter by date range
       * Filter by transaction type
       * Filter by specific networks

    2. **Process in batches:**
       ```javascript theme={null}
       async function processAllTransactions(address, processor) {
         let offset = 0;
         const limit = 250;

         while (true) {
           const params = new URLSearchParams({
             addresses: address,
             limit: limit.toString(),
             offset: offset.toString(),
             sort: 'DESC'
           });

           const response = await fetch(
             `https://api.octav.fi/v1/transactions?${params}`,
             {
               headers: {
                 'Authorization': `Bearer ${apiKey}`
               }
             }
           );

           const { transactions } = await response.json();

           if (transactions.length === 0) break;

           await processor(transactions);

           offset += transactions.length;

           if (transactions.length < limit) break;
         }
       }
       ```

    3. **Implement caching:**
       * Cache transaction pages locally
       * Only fetch new transactions since last sync
       * Use `startDate` to fetch only recent data
  </Accordion>
</AccordionGroup>

***

## Error Responses

<AccordionGroup>
  <Accordion title="400 Bad Request" icon="circle-exclamation">
    Invalid parameters provided.

    ```json theme={null}
    {
      "error": "Bad Request",
      "message": "limit must be between 1 and 250"
    }
    ```

    **Common causes:**

    * Missing required parameters (`addresses`, `limit`, `offset`)
    * Invalid parameter values
    * Invalid date format
  </Accordion>

  <Accordion title="404 Not Found" icon="circle-question">
    Address has more than 100,000 transactions.

    ```json theme={null}
    {
      "error": "Address not indexed",
      "message": "This address has over 100,000 transactions and is not indexed"
    }
    ```

    **Solution:** Contact support for assistance with high-volume addresses
  </Accordion>

  <Accordion title="401 Unauthorized" icon="lock">
    Authentication failed.

    ```json theme={null}
    {
      "error": "Unauthorized",
      "message": "Invalid API key"
    }
    ```

    **Solution:** Check your API key in the Authorization header
  </Accordion>

  <Accordion title="402 Payment Required" icon="credit-card">
    Insufficient credits.

    ```json theme={null}
    {
      "error": "Insufficient credits",
      "message": "Please purchase more credits to continue"
    }
    ```

    **Solution:** Purchase more credits at [data.octav.fi](https://data.octav.fi/)
  </Accordion>
</AccordionGroup>

***

## Related Endpoints

<CardGroup cols={2}>
  <Card title="Portfolio" icon="wallet" href="/api/endpoints/portfolio">
    View current portfolio holdings
  </Card>

  <Card title="Sync Transactions" icon="arrows-rotate" href="/api/endpoints/sync">
    Manually trigger transaction sync
  </Card>

  <Card title="Status" icon="signal" href="/api/endpoints/status">
    Check when transactions were last synced
  </Card>

  <Card title="Historical Portfolio" icon="clock" href="/api/endpoints/historical-portfolio">
    View portfolio at specific dates
  </Card>
</CardGroup>
