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
Session token for the authenticated user (from POST /v1/sessions)
Return Value
Returns an array of Card objects:
Last 4 digits of the card number
Card brand (visa, mastercard, amex, discover)
Expiration year (4 digits)
Name on the card (if provided during enrollment)
ISO 8601 timestamp of when the card was enrolled
Whether this is the user’s default 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
Common Errors
Code Cause Resolution SESSION_EXPIREDSession token expired Create new session SESSION_INVALIDInvalid session token Verify session creation USER_NOT_FOUNDUser has no enrollments Prompt 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