# List Pending Transfers
> Source: /api-reference/members/me/transfers/list-pending
> List pending transfers sent by or to the member
> Endpoint: GET /members/me/transfers/pending

## Overview [#overview]

Lists pending transfers sent by the member (direction=sent) or sent to the member's verified contacts (direction=received). Provides pagination and filtering options to manage transfer history and track gift statuses.

## Authentication [#authentication]

Requires a valid Clerk JWT token in the Authorization header.

## Query Parameters [#query-parameters]

<ParamField query="direction" type="string">
  Filter by direction: "sent" (transfers you sent) or "received" (transfers sent to your contacts). Default: "sent"
</ParamField>

<ParamField query="status" type="string">
  Filter by status: "PENDING", "CLAIMED", "EXPIRED", or "CANCELLED"
</ParamField>

<ParamField query="limit" type="number">
  Number of results per page. Default: 20, Maximum: 100
</ParamField>

<ParamField query="offset" type="number">
  Pagination offset. Default: 0
</ParamField>

<RequestExample>

```bash cURL - Sent Transfers
curl -X GET "http://localhost:3000/v1/members/me/transfers/pending?direction=sent&limit=10" \
  -H "Authorization: Bearer YOUR_CLERK_JWT"
```

```bash cURL - Received Transfers
curl -X GET "http://localhost:3000/v1/members/me/transfers/pending?direction=received&limit=10" \
  -H "Authorization: Bearer YOUR_CLERK_JWT"
```

```bash cURL - Filter by Status
curl -X GET "http://localhost:3000/v1/members/me/transfers/pending?status=PENDING&limit=20" \
  -H "Authorization: Bearer YOUR_CLERK_JWT"
```

```typescript TypeScript
// Get sent pending transfers
const getSentTransfers = async (limit = 20, offset = 0) => {
  const response = await fetch(`http://localhost:3000/v1/members/me/transfers/pending?direction=sent&limit=${limit}&offset=${offset}`, {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer YOUR_CLERK_JWT'
    }
  });
  
  return response.json();
};

// Get received pending transfers
const getReceivedTransfers = async (limit = 20, offset = 0) => {
  const response = await fetch(`http://localhost:3000/v1/members/me/transfers/pending?direction=received&limit=${limit}&offset=${offset}`, {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer YOUR_CLERK_JWT'
    }
  });
  
  return response.json();
};

// Get only pending (claimable) transfers
const getPendingTransfers = async () => {
  const response = await fetch('http://localhost:3000/v1/members/me/transfers/pending?status=PENDING&direction=received', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer YOUR_CLERK_JWT'
    }
  });
  
  return response.json();
};
```

</RequestExample>

## Response [#response]

<ResponseField name="items" type="array" required>
  List of pending transfer objects
  
  <Expandable title="array items">
    <ResponseField name="transferId" type="string" required>
      Unique transfer ID
    </ResponseField>
    
    <ResponseField name="senderExternalId" type="string" required>
      Sender's member external ID (ULID)
    </ResponseField>
    
    <ResponseField name="recipientEmail" type="string">
      Recipient email address (if sent to email)
    </ResponseField>
    
    <ResponseField name="recipientPhone" type="string">
      Recipient phone number (if sent to phone)
    </ResponseField>
    
    <ResponseField name="amount" type="number" required>
      Transfer amount in points
    </ResponseField>
    
    <ResponseField name="note" type="string">
      Optional message/note from sender
    </ResponseField>
    
    <ResponseField name="status" type="string" required>
      Transfer status: "PENDING", "CLAIMED", "EXPIRED", or "CANCELLED"
    </ResponseField>
    
    <ResponseField name="expiresAt" type="string" required>
      Expiration date (ISO 8601 format)
    </ResponseField>
    
    <ResponseField name="createdAt" type="string" required>
      Creation date (ISO 8601 format)
    </ResponseField>
    
    <ResponseField name="claimedAt" type="string">
      Claim date (ISO 8601 format, null if not claimed)
    </ResponseField>
    
    <ResponseField name="cancelledAt" type="string">
      Cancellation date (ISO 8601 format, null if not cancelled)
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="total" type="number" required>
  Total number of transfers matching filters
</ResponseField>

<ResponseField name="limit" type="number" required>
  Current pagination limit
</ResponseField>

<ResponseField name="offset" type="number" required>
  Current pagination offset
</ResponseField>

<ResponseExample>

```json 200 Response - Sent Transfers
{
  "items": [
    {
      "transferId": "123e4567-e89b-12d3-a456-426614174000",
      "senderExternalId": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
      "recipientEmail": "friend@example.com",
      "amount": 1000,
      "note": "Happy birthday!",
      "status": "PENDING",
      "expiresAt": "2025-02-15T00:00:00Z",
      "createdAt": "2025-01-15T10:30:00Z",
      "claimedAt": null,
      "cancelledAt": null
    },
    {
      "transferId": "456e7890-e89b-12d3-a456-426614174001",
      "senderExternalId": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
      "recipientPhone": "+1234567890",
      "amount": 500,
      "note": "Thanks for helping!",
      "status": "CLAIMED",
      "expiresAt": "2025-02-10T00:00:00Z",
      "createdAt": "2025-01-10T14:20:00Z",
      "claimedAt": "2025-01-12T09:15:00Z",
      "cancelledAt": null
    },
    {
      "transferId": "789e1234-e89b-12d3-a456-426614174002", 
      "senderExternalId": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
      "recipientEmail": "colleague@example.com",
      "amount": 750,
      "note": "Project bonus",
      "status": "CANCELLED",
      "expiresAt": "2025-02-20T00:00:00Z",
      "createdAt": "2025-01-20T16:45:00Z",
      "claimedAt": null,
      "cancelledAt": "2025-01-22T11:30:00Z"
    }
  ],
  "total": 23,
  "limit": 20,
  "offset": 0
}
```

```json 200 Response - Received Transfers
{
  "items": [
    {
      "transferId": "abc1234e-5678-9abc-def0-123456789abc",
      "senderExternalId": "01BRXT2YGJKP9MNPQRSTUVWXYZ",
      "recipientEmail": "myemail@example.com",
      "amount": 2000,
      "note": "Congratulations on your promotion!",
      "status": "PENDING",
      "expiresAt": "2025-02-25T00:00:00Z",
      "createdAt": "2025-01-25T12:00:00Z",
      "claimedAt": null,
      "cancelledAt": null
    }
  ],
  "total": 1,
  "limit": 20,
  "offset": 0
}
```

```json 200 Response - Empty Result
{
  "items": [],
  "total": 0,
  "limit": 20,
  "offset": 0
}
```

</ResponseExample>

## Transfer Directions [#transfer-directions]

### Sent Transfers (direction=sent) [#sent-transfers-directionsent]
- **Your Transfers**: Transfers you created and sent to others
- **Management**: Can cancel pending transfers
- **Tracking**: Monitor claim status and expiration
- **Use Case**: Manage outgoing gifts and recover points

### Received Transfers (direction=received) [#received-transfers-directionreceived]  
- **Incoming Gifts**: Transfers sent to your verified contacts
- **Claimable**: Can claim pending transfers
- **Visibility**: See who sent you gifts
- **Use Case**: Claim pending points and track gift history

## Transfer Statuses [#transfer-statuses]

### PENDING [#pending]
- **Description**: Transfer created but not yet claimed
- **Actions**: Can be cancelled (if sent) or claimed (if received)
- **Expiration**: Will expire automatically after 30 days
- **Points**: Held in escrow until claimed or expired

### CLAIMED [#claimed]
- **Description**: Recipient has claimed the transfer
- **Actions**: No further actions available
- **Points**: Transferred to recipient's account
- **Finality**: Cannot be reversed or cancelled

### EXPIRED [#expired]
- **Description**: Transfer expired without being claimed
- **Actions**: No actions available
- **Points**: Automatically returned to sender
- **Timeline**: Expires 30 days after creation

### CANCELLED [#cancelled]
- **Description**: Sender cancelled the transfer
- **Actions**: No further actions available
- **Points**: Returned to sender's account
- **Timeline**: Can be cancelled anytime before claim/expiry

## Pagination [#pagination]

### Pagination Parameters [#pagination-parameters]
- **limit**: Results per page (1-100, default 20)
- **offset**: Skip number of results (default 0)
- **total**: Total matching transfers
- **Navigation**: Use offset + limit for next page

### Pagination Example [#pagination-example]
```typescript
const getAllTransfers = async () => {
  const allTransfers = [];
  let offset = 0;
  const limit = 50;
  
  while (true) {
    const response = await fetch(
      `/api/members/me/transfers/pending?limit=${limit}&offset=${offset}`
    );
    const data = await response.json();
    
    allTransfers.push(...data.items);
    
    if (offset + limit >= data.total) {
      break; // No more pages
    }
    
    offset += limit;
  }
  
  return allTransfers;
};
```

## Use Cases [#use-cases]

### Gift Management Dashboard [#gift-management-dashboard]
```typescript
const TransferDashboard = () => {
  const [sentTransfers, setSentTransfers] = useState([]);
  const [receivedTransfers, setReceivedTransfers] = useState([]);
  
  useEffect(() => {
    // Load sent transfers
    fetch('/api/members/me/transfers/pending?direction=sent')
      .then(response => response.json())
      .then(data => setSentTransfers(data.items));
      
    // Load received transfers  
    fetch('/api/members/me/transfers/pending?direction=received')
      .then(response => response.json())
      .then(data => setReceivedTransfers(data.items));
  }, []);
  
  const pendingSent = sentTransfers.filter(t => t.status === 'PENDING');
  const pendingReceived = receivedTransfers.filter(t => t.status === 'PENDING');
  
  return (
    <div>
      <h3>Pending Gifts Sent ({pendingSent.length})</h3>
      {pendingSent.map(transfer => (
        <GiftCard 
          key={transfer.transferId}
          transfer={transfer}
          actions={['cancel']}
        />
      ))}
      
      <h3>Pending Gifts Received ({pendingReceived.length})</h3>
      {pendingReceived.map(transfer => (
        <GiftCard 
          key={transfer.transferId}
          transfer={transfer}
          actions={['claim']}
        />
      ))}
    </div>
  );
};
```

### Expiry Monitoring [#expiry-monitoring]
```typescript
const checkExpiringTransfers = async () => {
  const response = await fetch('/api/members/me/transfers/pending?direction=sent&status=PENDING');
  const data = await response.json();
  
  const now = new Date();
  const warning = 3 * 24 * 60 * 60 * 1000; // 3 days in ms
  
  const expiringSoon = data.items.filter(transfer => {
    const expiryDate = new Date(transfer.expiresAt);
    return (expiryDate.getTime() - now.getTime()) < warning;
  });
  
  if (expiringSoon.length > 0) {
    showNotification({
      title: `${expiringSoon.length} gifts expiring soon`,
      message: 'Consider cancelling to recover points',
      actions: ['View Transfers', 'Cancel All']
    });
  }
  
  return expiringSoon;
};
```

### Auto-Claim System [#auto-claim-system]
```typescript
const autoClaimPendingGifts = async () => {
  // Get all pending received transfers
  const response = await fetch('/api/members/me/transfers/pending?direction=received&status=PENDING');
  const data = await response.json();
  
  let totalClaimed = 0;
  const results = [];
  
  for (const transfer of data.items) {
    try {
      // Attempt to claim by email or phone
      const claimData = transfer.recipientEmail 
        ? { email: transfer.recipientEmail }
        : { phone: transfer.recipientPhone };
        
      const claimResponse = await fetch('/api/members/me/transfers/claim', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(claimData)
      });
      
      const claimResult = await claimResponse.json();
      totalClaimed += claimResult.totalClaimed || 0;
      results.push({ transferId: transfer.transferId, success: true });
    } catch (error) {
      results.push({ transferId: transfer.transferId, success: false, error });
    }
  }
  
  if (totalClaimed > 0) {
    showNotification(`Auto-claimed ${totalClaimed} points from ${results.filter(r => r.success).length} gifts!`);
  }
  
  return { totalClaimed, results };
};
```

## Filtering and Sorting [#filtering-and-sorting]

### Filter Combinations [#filter-combinations]
```typescript
// Get all pending transfers you sent
const pendingSent = await fetch('/api/transfers/pending?direction=sent&status=PENDING');

// Get all claimed gifts you received  
const claimedReceived = await fetch('/api/transfers/pending?direction=received&status=CLAIMED');

// Get expired transfers with pagination
const expiredTransfers = await fetch('/api/transfers/pending?status=EXPIRED&limit=50&offset=100');
```

### Sorting (Client-side) [#sorting-client-side]
```typescript
const sortTransfers = (transfers: Transfer[], sortBy: 'date' | 'amount' | 'status') => {
  return [...transfers].sort((a, b) => {
    switch (sortBy) {
      case 'date':
        return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
      case 'amount':
        return b.amount - a.amount;
      case 'status':
        return a.status.localeCompare(b.status);
      default:
        return 0;
    }
  });
};
```

## Related Endpoints [#related-endpoints]

- [Create Transfer](/api-reference/members/me/transfers/create-transfer) - Create new pending transfers
- [Claim Pending Transfer](/api-reference/members/me/transfers/claim-pending) - Claim received transfers
- [Cancel Pending Transfer](/api-reference/members/me/transfers/cancel-pending) - Cancel sent transfers  
- [Get Transfer Limits](/api-reference/members/me/transfers/get-limits) - Check available transfer capacity
