> ## 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.

# How to Get All Solana Wallet Transfers

> Track all incoming and outgoing token transfers for any Solana wallet. See sender/recipient information, amounts, and timestamps for complete transfer history.

> [!NOTE]
>
> The Wallet API is in Beta. Endpoints and response formats may change.

## Overview

The Token Transfers endpoint retrieves all token transfer activity for a Solana wallet, including detailed sender and recipient information. Unlike the full [transaction history](https://www.helius.dev/docs/wallet-api/history.md), this endpoint focuses specifically on transfers, making it ideal for payment tracking and transfer monitoring.

The endpoint returns up to 100 transfers per request (default 50). Use the `cursor` parameter with `pagination.nextCursor` to fetch the next page, and read `pagination.hasMore` to know when more results are available.

## When to use this

Use the Token Transfers API when you need to:

* **Track payments**: monitor incoming payments for payment processors.
* **Build a transfer feed**: display a simple "sent/received" activity feed.
* **Monitor specific tokens**: track transfers of a specific token (e.g., USDC payments).
* **Identify counterparties**: see who sent or received tokens.
* **Generate receipts**: create payment receipts with sender/recipient details.
* **Detect suspicious activity**: monitor unusual transfer patterns.

## Quickstart

### Basic transfers query

Get recent incoming and outgoing transfers:

> [tab] JavaScript
>
> ```javascript theme={"system"}
> const getWalletTransfers = async (address) => {
>   const url = `https://api.helius.xyz/v1/wallet/${address}/transfers?api-key=YOUR_API_KEY`;
>
>   const response = await fetch(url);
>   if (!response.ok) {
>     throw new Error(`HTTP error! status: ${response.status}`);
>   }
>
>   const data = await response.json();
>
>   console.log(`Found ${data.data.length} transfers`);
>
>   // Display recent transfers
>   data.data.forEach(transfer => {
>     const date = new Date(transfer.timestamp * 1000).toLocaleString();
>     const direction = transfer.direction === 'in' ? 'Received' : 'Sent';
>     const counterparty = transfer.counterparty.slice(0, 8) + '...';
>
>     console.log(`\n${direction} - ${date}`);
>     console.log(`Amount: ${transfer.amount} ${transfer.symbol || transfer.mint.slice(0, 8) + '...'}`);
>     console.log(`${transfer.direction === 'in' ? 'From' : 'To'}: ${counterparty}`);
>     console.log(`Signature: ${transfer.signature.slice(0, 20)}...`);
>   });
>
>   return data;
> };
>
> getWalletTransfers("86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY");
> ```

> [tab] Python
>
> ```python theme={"system"}
> import requests
> from datetime import datetime
>
> def get_wallet_transfers(address: str):
>     url = f"https://api.helius.xyz/v1/wallet/{address}/transfers"
>     headers = {"X-Api-Key": "YOUR_API_KEY"}
>
>     response = requests.get(url, headers=headers)
>     response.raise_for_status()
>
>     data = response.json()
>
>     print(f"Found {len(data['data'])} transfers")
>
>     # Display recent transfers
>     for transfer in data['data']:
>         date = datetime.fromtimestamp(transfer['timestamp']).strftime('%Y-%m-%d %H:%M:%S')
>         direction = 'Received' if transfer['direction'] == 'in' else 'Sent'
>         counterparty = transfer['counterparty'][:8] + '...'
>         symbol = transfer.get('symbol') or transfer['mint'][:8] + '...'
>
>         print(f"\n{direction} - {date}")
>         print(f"Amount: {transfer['amount']} {symbol}")
>         print(f"{'From' if transfer['direction'] == 'in' else 'To'}: {counterparty}")
>         print(f"Signature: {transfer['signature'][:20]}...")
>
>     return data
>
> get_wallet_transfers("86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY")
> ```

> [tab] cURL
>
> ```bash theme={"system"}
> curl "https://api.helius.xyz/v1/wallet/86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY/transfers?api-key=YOUR_API_KEY"
> ```

### Filter by direction

Filter the results client-side to get only incoming or outgoing transfers:

> [tab] Incoming Only
>
> ```javascript theme={"system"}
> const getIncomingTransfers = async (address) => {
>   const data = await getWalletTransfers(address);
>
>   const incoming = data.data.filter(t => t.direction === 'in');
>
>   console.log(`Received ${incoming.length} incoming transfers`);
>
>   incoming.forEach(transfer => {
>     console.log(`Received ${transfer.amount} ${transfer.symbol} from ${transfer.counterparty.slice(0, 8)}...`);
>   });
>
>   return incoming;
> };
> ```

> [tab] Outgoing Only
>
> ```javascript theme={"system"}
> const getOutgoingTransfers = async (address) => {
>   const data = await getWalletTransfers(address);
>
>   const outgoing = data.data.filter(t => t.direction === 'out');
>
>   console.log(`Made ${outgoing.length} outgoing transfers`);
>
>   outgoing.forEach(transfer => {
>     console.log(`Sent ${transfer.amount} ${transfer.symbol} to ${transfer.counterparty.slice(0, 8)}...`);
>   });
>
>   return outgoing;
> };
> ```

## Query parameters

| Parameter | Type | Default | Description |
| - | - | - | - |
| `limit` | integer | 50 | Maximum number of transfers to return (1-100) |
| `cursor` | string | - | Pagination cursor from previous response |

## Response format

```json theme={"system"}
{
  "data": [
    {
      "signature": "5wHu1qwD7Jsj3xqWjdSEJmYr3Q5f5RjXqjqQJ7jqEj7jqEj7jqEj7jqEj7jqEj7jqE",
      "timestamp": 1704067200,
      "direction": "in",
      "counterparty": "HXsKP7wrBWaQ8T2Vtjry3Nj3oUgwYcqq9vrHDM12G664",
      "mint": "So11111111111111111111111111111111111111111",
      "symbol": "SOL",
      "amount": 1.5,
      "amountRaw": "1500000000",
      "decimals": 9
    },
    {
      "signature": "4aHu2qwD8Jtj4xqWjdSEJmYr3Q5f5RjXqjqQJ7jqEj7jqEj7jqEj7jqEj7jqEj7jqE",
      "timestamp": 1704067100,
      "direction": "out",
      "counterparty": "2ojv9BAiHUrvsm9gxDe7fJSzbNZSJcxZvf8dqmWGHG8S",
      "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "symbol": "USDC",
      "amount": 100.0,
      "amountRaw": "100000000",
      "decimals": 6
    }
  ],
  "pagination": {
    "hasMore": true,
    "nextCursor": "5wHu1qwD7Jsj3xqWjdSEJmYr3Q5f5RjXqjqQJ7jqEj7jqEj7jqEj7jqEj7jqEj7jqE"
  }
}
```

### Field notes

* **`direction`**: relative to the wallet you're querying. `in` is tokens **received** (incoming payment); `out` is tokens **sent** (outgoing payment).
* **`counterparty`**: for `in` transfers, the sender; for `out` transfers, the recipient.
* **`amount`**: human-readable transfer amount, already divided by `decimals`. Use this for display (e.g., `1.5` SOL, `100.0` USDC).
* **`amountRaw`**: the same amount as a raw integer string, before decimal adjustment (e.g., `"1500000000"` for 1.5 SOL). Serialized as a string to avoid floating-point precision loss. Use this for on-chain instructions or precise arithmetic: `amount = parseInt(amountRaw) / 10**decimals`.
* **`mint`**: token mint address (`So11111111111111111111111111111111111111111` for native SOL).
* **`symbol`**: token symbol. Not all tokens have one; fall back to the mint address when `symbol` is `null`.

## Use cases

### Track payment history for a merchant

Monitor incoming USDC payments:

```javascript theme={"system"}
const trackMerchantPayments = async (merchantWallet) => {
  const data = await getWalletTransfers(merchantWallet);

  // Filter for incoming USDC transfers
  const usdcPayments = data.data.filter(t =>
    t.direction === 'in' &&
    t.mint === 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' // USDC
  );

  console.log(`Received ${usdcPayments.length} USDC payments`);

  const totalReceived = usdcPayments.reduce((sum, t) => sum + t.amount, 0);
  console.log(`Total USDC Received: $${totalReceived.toFixed(2)}`);

  // Display each payment
  usdcPayments.forEach(payment => {
    const date = new Date(payment.timestamp * 1000).toLocaleString();
    console.log(`${date}: $${payment.amount} from ${payment.counterparty}`);
  });

  return {
    count: usdcPayments.length,
    total: totalReceived,
    payments: usdcPayments
  };
};
```

### Generate a payment receipt

Create a detailed receipt for a specific transfer:

```javascript theme={"system"}
const generatePaymentReceipt = async (address, signature) => {
  const data = await getWalletTransfers(address);

  const transfer = data.data.find(t => t.signature === signature);

  if (!transfer) {
    console.log('Transfer not found');
    return null;
  }

  const receipt = {
    receiptId: transfer.signature.slice(0, 16),
    date: new Date(transfer.timestamp * 1000).toISOString(),
    type: transfer.direction === 'in' ? 'Payment Received' : 'Payment Sent',
    amount: `${transfer.amount} ${transfer.symbol || 'tokens'}`,
    from: transfer.direction === 'in' ? transfer.counterparty : address,
    to: transfer.direction === 'out' ? transfer.counterparty : address,
    transactionUrl: `https://orbmarkets.io/tx/${transfer.signature}`
  };

  console.log('--- PAYMENT RECEIPT ---');
  Object.entries(receipt).forEach(([key, value]) => {
    console.log(`${key}: ${value}`);
  });

  return receipt;
};
```

### Monitor suspicious transfer patterns

Detect unusual transfer activity:

```javascript theme={"system"}
const detectSuspiciousActivity = async (address) => {
  const data = await getWalletTransfers(address);

  const recentTransfers = data.data.filter(t => {
    const hourAgo = Date.now() / 1000 - 3600;
    return t.timestamp > hourAgo;
  });

  // Check for high frequency
  if (recentTransfers.length > 100) {
    console.log(`Warning: ${recentTransfers.length} transfers in the last hour`);
  }

  // Check for large amounts
  const largeTransfers = recentTransfers.filter(t => {
    // Assuming USDC/stablecoins
    return t.amount > 10000 && t.decimals === 6;
  });

  if (largeTransfers.length > 0) {
    console.log(`Warning: ${largeTransfers.length} large transfers (>$10k) in the last hour`);
  }

  // Check for transfers to same address
  const counterparties = recentTransfers.map(t => t.counterparty);
  const duplicates = counterparties.filter((item, index) => counterparties.indexOf(item) !== index);

  if (duplicates.length > 5) {
    console.log(`Warning: Multiple transfers to the same address`);
  }

  return {
    recentCount: recentTransfers.length,
    largeTransfers: largeTransfers.length,
    suspiciousPatterns: duplicates.length > 5
  };
};
```

### Build a transfer activity feed

Create a user-friendly activity feed:

```javascript theme={"system"}
const buildTransferFeed = async (address) => {
  const data = await getWalletTransfers(address);

  const feed = data.data.map(transfer => {
    const date = new Date(transfer.timestamp * 1000);
    const timeAgo = getTimeAgo(date);

    return {
      id: transfer.signature,
      direction: transfer.direction,
      title: transfer.direction === 'in' ? 'Received' : 'Sent',
      subtitle: `${transfer.amount} ${transfer.symbol || 'tokens'}`,
      description: transfer.direction === 'in'
        ? `from ${transfer.counterparty.slice(0, 8)}...`
        : `to ${transfer.counterparty.slice(0, 8)}...`,
      timeAgo,
      explorerUrl: `https://orbmarkets.io/tx/${transfer.signature}`
    };
  });

  return feed;
};

function getTimeAgo(date) {
  const seconds = Math.floor((new Date() - date) / 1000);

  if (seconds < 60) return 'Just now';
  if (seconds < 3600) return `${Math.floor(seconds / 60)}m ago`;
  if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ago`;
  return `${Math.floor(seconds / 86400)}d ago`;
}
```

### Reconcile payments

Match transfers against expected payments:

```javascript theme={"system"}
const reconcilePayments = async (address, expectedPayments) => {
  const data = await getWalletTransfers(address);

  const recentTransfers = data.data.filter(t =>
    t.direction === 'in' &&
    t.mint === 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' // USDC
  );

  const reconciliation = expectedPayments.map(expected => {
    const match = recentTransfers.find(t =>
      Math.abs(t.amount - expected.amount) < 0.01 &&
      t.counterparty === expected.from
    );

    return {
      orderId: expected.orderId,
      expectedAmount: expected.amount,
      status: match ? 'Received' : 'Pending',
      receivedAmount: match?.amount,
      signature: match?.signature,
      timestamp: match?.timestamp
    };
  });

  console.log('Payment Reconciliation:');
  reconciliation.forEach(r => {
    console.log(`Order ${r.orderId}: ${r.status}`);
  });

  return reconciliation;
};

// Example usage
const expected = [
  { orderId: 'ORDER-001', amount: 100.00, from: 'ABC...' },
  { orderId: 'ORDER-002', amount: 250.50, from: 'XYZ...' }
];

reconcilePayments("86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY", expected);
```

## Pagination

For wallets with many transfers, page through results with the `cursor` parameter and `pagination.hasMore`:

```javascript theme={"system"}
const getAllTransfers = async (address) => {
  let allTransfers = [];
  let cursor = null;

  do {
    const url = cursor
      ? `https://api.helius.xyz/v1/wallet/${address}/transfers?api-key=YOUR_API_KEY&cursor=${cursor}`
      : `https://api.helius.xyz/v1/wallet/${address}/transfers?api-key=YOUR_API_KEY`;

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

    allTransfers = allTransfers.concat(data.data);
    cursor = data.pagination.hasMore ? data.pagination.nextCursor : null;

    console.log(`Fetched ${allTransfers.length} transfers so far...`);

  } while (cursor);

  console.log(`\nTotal transfers: ${allTransfers.length}`);
  return allTransfers;
};
```

## Best practices

* **Filter client-side for specific tokens.** The API returns all token transfers. Filter by `mint` address to track specific tokens like USDC or SOL.
* **Combine with the Identity API.** Use the [Identity](https://www.helius.dev/docs/wallet-api/identity.md) endpoint to show human-readable names for known counterparties (exchanges, protocols, and others).
* **Cache recent transfers.** Transfer data doesn't change. Cache results and only fetch new transfers since your last query.
* **Paginate for complete history.** Implement pagination to handle wallets with thousands of transfers efficiently.
* **Handle a missing symbol.** Not all tokens have a `symbol` field. Fall back to the mint address when `symbol` is `null`.

## Transfers vs transaction history

| Feature | Transfers | Transaction History |
| - | - | - |
| **Focus** | Only token transfers | All transaction types |
| **Data** | Sender/recipient info | Balance changes for all tokens |
| **Use case** | Payment tracking | Complete activity log |
| **Performance** | Faster, simpler | More comprehensive |

Use [Transfers](https://www.helius.dev/docs/wallet-api/transfers.md) when you only care about payments. Use [Transaction History](https://www.helius.dev/docs/wallet-api/history.md) when you need complete balance change data.

## Common errors

| Error Code | Description | Solution |
| - | - | - |
| 400 | Invalid wallet address format | Verify the address is a valid base58 Solana address |
| 401 | Missing or invalid API key | Check your API key is included in the request |
| 429 | Rate limit exceeded | Reduce request frequency or upgrade your plan |

## Next steps

> [card] [Wallet History](https://www.helius.dev/docs/wallet-api/history.md)
>
> Complete transaction history with per-transaction balance changes.

> [card] [Wallet API Overview](https://www.helius.dev/docs/wallet-api/overview.md)
>
> All Wallet API endpoints and shared conventions.

> [card] [API Reference](https://www.helius.dev/docs/api-reference/wallet-api/transfers.md)
>
> Request and response schemas for token transfers.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.