Skip to main content

Overview

The listCards() method retrieves all cards enrolled by a user. It returns card metadata (last 4 digits, brand, expiration) without exposing sensitive PAN data.

Method Signature

prava.listCards(sessionToken: string): Promise<Card[]>

Parameters

sessionToken
string
required
Session token for the authenticated user (from POST /v1/sessions)

Return Value

Returns an array of Card objects:
cards
Card[]

Example

import { useEffect, useState } from 'react';
import { PravaSDK } from '@prava/sdk-core';

function CardList() {
  const [cards, setCards] = useState([]);
  const [loading, setLoading] = useState(true);

  const prava = new PravaSDK({
    publishableKey: 'pk_sandbox_your_key',
    environment: 'sandbox'
  });

  useEffect(() => {
    async function fetchCards() {
      try {
        // Get session token from your backend
        const { session_token } = await fetch('/api/create-session', {
          method: 'POST'
        }).then(r => r.json());

        // Fetch cards
        const cards = await prava.listCards(session_token);
        setCards(cards);
      } catch (error) {
        console.error('Failed to load cards:', error);
      } finally {
        setLoading(false);
      }
    }

    fetchCards();
  }, []);

  if (loading) return <div>Loading cards...</div>;

  if (cards.length === 0) {
    return <div>No cards enrolled. <button>Add Card</button></div>;
  }

  return (
    <div>
      <h2>Your Cards</h2>
      {cards.map(card => (
        <div key={card.id} className="card-item">
          <img src={`/logos/${card.brand}.svg`} alt={card.brand} />
          <span>{card.brand.toUpperCase()} •••• {card.last4}</span>
          <span>Expires {card.exp_month}/{card.exp_year}</span>
          {card.is_default && <span className="badge">Default</span>}
        </div>
      ))}
    </div>
  );
}

Use Cases

Payment Method Selection

Allow users to choose which card to use for a payment:
const cards = await prava.listCards(sessionToken);

// Present cards to user
const selectedCardId = await showCardSelector(cards);

// Use selected card for intent
const intent = await prava.registerIntent({
  cardId: selectedCardId,
  amount: 99.99,
  merchant: 'Acme Store'
});

Card Management Dashboard

Build a card management interface:
function CardManagement() {
  const [cards, setCards] = useState([]);

  async function handleAddCard() {
    const result = await prava.collectPAN({...});
    setCards([...cards, result]);
  }

  async function handleRemoveCard(cardId) {
    await prava.removeCard(cardId);
    setCards(cards.filter(c => c.id !== cardId));
  }

  async function handleSetDefault(cardId) {
    await prava.setDefaultCard(cardId);
    setCards(cards.map(c => ({
      ...c,
      is_default: c.id === cardId
    })));
  }

  return (
    <div>
      {cards.map(card => (
        <CardItem
          key={card.id}
          card={card}
          onRemove={() => handleRemoveCard(card.id)}
          onSetDefault={() => handleSetDefault(card.id)}
        />
      ))}
      <button onClick={handleAddCard}>+ Add Card</button>
    </div>
  );
}

Card Expiration Handling

Check for expired cards and prompt users to update:
const cards = await prava.listCards(sessionToken);
const now = new Date();
const currentYear = now.getFullYear();
const currentMonth = now.getMonth() + 1;

const expiredCards = cards.filter(card => {
  if (card.exp_year < currentYear) return true;
  if (card.exp_year === currentYear && card.exp_month < currentMonth) return true;
  return false;
});

if (expiredCards.length > 0) {
  console.warn(`${expiredCards.length} card(s) expired`);
  // Show update card flow
}

Error Handling

error
PravaError

Common Errors

CodeCauseResolution
SESSION_EXPIREDSession token expiredCreate new session
SESSION_INVALIDInvalid session tokenVerify session creation
USER_NOT_FOUNDUser has no enrollmentsPrompt to add first card

Security Considerations

Card metadata is safe to display: The listCards() response contains only non-sensitive data (last 4, brand, expiry). Full PANs are never returned by the API.
Session tokens authenticate the user: Never expose session tokens in client-side logs or error messages, as they grant access to user card metadata.

Caching Recommendations

For better UX, consider caching the card list:
// Cache cards for 5 minutes
const CACHE_TTL = 5 * 60 * 1000;
let cardCache = null;
let cacheTime = 0;

async function getCards(sessionToken) {
  if (cardCache && Date.now() - cacheTime < CACHE_TTL) {
    return cardCache;
  }

  cardCache = await prava.listCards(sessionToken);
  cacheTime = Date.now();
  return cardCache;
}

// Invalidate cache after adding/removing cards
function invalidateCardCache() {
  cardCache = null;
  cacheTime = 0;
}

Next Steps