Journey Docs
Members APITransfers

List Pending Transfers

List pending transfers sent by or to the member

GET/members/me/transfers/pending

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

Requires a valid Clerk JWT token in the Authorization header.

Query Parameters

directionquerystring

Filter by direction: "sent" (transfers you sent) or "received" (transfers sent to your contacts). Default: "sent"

statusquerystring

Filter by status: "PENDING", "CLAIMED", "EXPIRED", or "CANCELLED"

limitquerynumber

Number of results per page. Default: 20, Maximum: 100

offsetquerynumber

Pagination offset. Default: 0

Request

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

Response

itemsarrayrequired

List of pending transfer objects

array items
transferIdstringrequired

Unique transfer ID

senderExternalIdstringrequired

Sender's member external ID (ULID)

recipientEmailstring

Recipient email address (if sent to email)

recipientPhonestring

Recipient phone number (if sent to phone)

amountnumberrequired

Transfer amount in points

notestring

Optional message/note from sender

statusstringrequired

Transfer status: "PENDING", "CLAIMED", "EXPIRED", or "CANCELLED"

expiresAtstringrequired

Expiration date (ISO 8601 format)

createdAtstringrequired

Creation date (ISO 8601 format)

claimedAtstring

Claim date (ISO 8601 format, null if not claimed)

cancelledAtstring

Cancellation date (ISO 8601 format, null if not cancelled)

totalnumberrequired

Total number of transfers matching filters

limitnumberrequired

Current pagination limit

offsetnumberrequired

Current pagination offset

Response

{
  "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
}

Transfer Directions

Sent Transfers (direction=sent)

  • 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)

  • 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

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

  • Description: Recipient has claimed the transfer
  • Actions: No further actions available
  • Points: Transferred to recipient's account
  • Finality: Cannot be reversed or cancelled

EXPIRED

  • Description: Transfer expired without being claimed
  • Actions: No actions available
  • Points: Automatically returned to sender
  • Timeline: Expires 30 days after creation

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

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

Gift Management Dashboard

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

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

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

Filter Combinations

// 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)

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;
    }
  });
};

On this page