Documentation Index Fetch the complete documentation index at: https://docs.baanx.com/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Card lifecycle management gives users control over their card’s operational state. The primary operations are freezing (temporarily disabling) and unfreezing (reactivating) cards for security purposes.
Freezing a card is a temporary, reversible action. Users can freeze and unfreeze their cards as many times as needed.
Card States
Understanding card states is essential for proper lifecycle management:
Active Card is operational and can process transactions
Frozen Card is temporarily disabled by user
Blocked Card is permanently disabled by system
State Transitions
State Details
Description : Normal operational state. Card can be used for all transactions.Allowed Operations :
Make purchases (online, in-store)
View card details
View/set PIN
Check transaction history
Freeze card
User Actions :
✅ Use card for purchases
✅ Freeze card if needed
✅ View card details and PIN
✅ Change PIN
Description : Temporarily disabled by user for security. Reversible.Allowed Operations :
View card details (read-only)
Check transaction history
Unfreeze card
Blocked Operations :
❌ Make purchases (all declined)
❌ Change PIN
❌ ATM withdrawals
Common Use Cases :
Lost wallet (not sure if card is missing)
Traveling and not using card
Suspicious activity detected
Temporary security measure
User Actions :
✅ Unfreeze when ready to use again
❌ Cannot make purchases while frozen
Description : Permanently disabled by system. Not reversible.Allowed Operations :
View transaction history
Request replacement card
Blocked Operations :
❌ Make purchases
❌ Unfreeze card
❌ Change PIN
❌ All card operations
Common Causes :
Fraud detection triggered
Multiple failed PIN attempts
Compliance/KYC issues
Card reported as lost/stolen (permanent)
Regulatory requirement
Resolution :
Contact support to understand reason
Resolve underlying issue (if applicable)
Request replacement card
Freezing a Card
Temporarily disable a card to prevent unauthorized transactions.
When to Freeze
Wallet misplaced (not confirmed lost)
Suspicious transaction notification
Traveling and not using card
Taking a break from spending
Device with saved card details lost
API Request
JavaScript/Node.js
Python
cURL
const response = await fetch ( 'https://dev.api.baanx.com/v1/card/freeze' , {
method: 'POST' ,
headers: {
'X-Client-ID' : 'your_client_id' ,
'Authorization' : `Bearer ${ userAccessToken } `
}
});
const result = await response . json ();
if ( result . success ) {
console . log ( 'Card frozen successfully' );
// Update UI to show frozen state
}
Response
Success (200)
Error (400)
Error (404)
Card has been frozen. All transaction attempts will now be declined until the card is unfrozen. {
"message" : "Card is already frozen" ,
"code" : "INVALID_STATE"
}
Card is already in frozen state. No action needed. {
"message" : "Card not found"
}
User doesn’t have a card. Direct them to order a card first.
Implementation Example
React Component
Flask Backend
import { useState } from 'react' ;
export function CardFreezeButton ({ clientId , accessToken , currentStatus }) {
const [ loading , setLoading ] = useState ( false );
const [ status , setStatus ] = useState ( currentStatus );
const [ error , setError ] = useState ( null );
async function freezeCard () {
setLoading ( true );
setError ( null );
try {
const response = await fetch ( '/v1/card/freeze' , {
method: 'POST' ,
headers: {
'X-Client-ID' : clientId ,
'Authorization' : `Bearer ${ accessToken } `
}
});
if ( ! response . ok ) {
const errorData = await response . json ();
throw new Error ( errorData . message || 'Failed to freeze card' );
}
const result = await response . json ();
if ( result . success ) {
setStatus ( 'FROZEN' );
// Optionally show success notification
}
} catch ( err ) {
setError ( err . message );
} finally {
setLoading ( false );
}
}
if ( status === 'FROZEN' ) {
return (
< div className = "card-frozen" >
< span > 🥶 Card is frozen </ span >
</ div >
);
}
return (
< div >
< button
onClick = { freezeCard }
disabled = { loading || status !== 'ACTIVE' }
className = "btn-freeze"
>
{ loading ? 'Freezing...' : 'Freeze Card' }
</ button >
{ error && (
< div className = "error-message" >
{ error }
</ div >
) }
</ div >
);
}
Unfreezing a Card
Reactivate a frozen card to resume normal operations.
When to Unfreeze
Suspicious activity resolved
API Request
JavaScript/Node.js
Python
cURL
const response = await fetch ( 'https://dev.api.baanx.com/v1/card/unfreeze' , {
method: 'POST' ,
headers: {
'X-Client-ID' : 'your_client_id' ,
'Authorization' : `Bearer ${ userAccessToken } `
}
});
const result = await response . json ();
if ( result . success ) {
console . log ( 'Card unfrozen - ready to use' );
}
Response
Success (200)
Error (400)
Error (404)
Card has been unfrozen and is now active. Transactions will be authorized normally. {
"message" : "Card is not frozen" ,
"code" : "INVALID_STATE"
}
Card is not in frozen state (may be active or blocked). Check current status. {
"message" : "Card not found"
}
User doesn’t have a card.
Implementation Example
React Component
Flask Backend
import { useState } from 'react' ;
export function CardUnfreezeButton ({ clientId , accessToken , currentStatus }) {
const [ loading , setLoading ] = useState ( false );
const [ status , setStatus ] = useState ( currentStatus );
const [ error , setError ] = useState ( null );
async function unfreezeCard () {
setLoading ( true );
setError ( null );
try {
const response = await fetch ( '/v1/card/unfreeze' , {
method: 'POST' ,
headers: {
'X-Client-ID' : clientId ,
'Authorization' : `Bearer ${ accessToken } `
}
});
if ( ! response . ok ) {
const errorData = await response . json ();
throw new Error ( errorData . message || 'Failed to unfreeze card' );
}
const result = await response . json ();
if ( result . success ) {
setStatus ( 'ACTIVE' );
// Show success notification
}
} catch ( err ) {
setError ( err . message );
} finally {
setLoading ( false );
}
}
if ( status === 'ACTIVE' ) {
return (
< div className = "card-active" >
< span > ✅ Card is active </ span >
</ div >
);
}
if ( status === 'BLOCKED' ) {
return (
< div className = "card-blocked" >
< span > 🚫 Card is blocked - contact support </ span >
</ div >
);
}
return (
< div >
< button
onClick = { unfreezeCard }
disabled = { loading || status !== 'FROZEN' }
className = "btn-unfreeze"
>
{ loading ? 'Unfreezing...' : 'Unfreeze Card' }
</ button >
{ error && (
< div className = "error-message" >
{ error }
</ div >
) }
</ div >
);
}
Complete Card Control Component
Here’s a comprehensive component that handles all card states:
import { useState , useEffect } from 'react' ;
export function CardControl ({ clientId , accessToken }) {
const [ card , setCard ] = useState ( null );
const [ loading , setLoading ] = useState ( false );
const [ error , setError ] = useState ( null );
useEffect (() => {
fetchCardStatus ();
}, []);
async function fetchCardStatus () {
try {
const response = await fetch ( '/v1/card/status' , {
headers: {
'X-Client-ID' : clientId ,
'Authorization' : `Bearer ${ accessToken } `
}
});
if ( response . ok ) {
const cardData = await response . json ();
setCard ( cardData );
}
} catch ( err ) {
console . error ( 'Failed to fetch card status:' , err );
}
}
async function toggleFreeze () {
setLoading ( true );
setError ( null );
try {
const endpoint = card . status === 'ACTIVE' ? 'freeze' : 'unfreeze' ;
const response = await fetch ( `/v1/card/ ${ endpoint } ` , {
method: 'POST' ,
headers: {
'X-Client-ID' : clientId ,
'Authorization' : `Bearer ${ accessToken } `
}
});
if ( ! response . ok ) {
const errorData = await response . json ();
throw new Error ( errorData . message );
}
// Refresh card status
await fetchCardStatus ();
} catch ( err ) {
setError ( err . message );
} finally {
setLoading ( false );
}
}
if ( ! card ) {
return < div > Loading card details... </ div > ;
}
return (
< div className = "card-control" >
< div className = "card-info" >
< h3 > Card ending in { card . panLast4 } </ h3 >
< CardStatusBadge status = { card . status } />
</ div >
{ card . status === 'BLOCKED' ? (
< div className = "blocked-message" >
< p > ⚠️ This card has been blocked and cannot be used. </ p >
< p > Please contact support for assistance. </ p >
< button > Contact Support </ button >
</ div >
) : (
< div className = "card-actions" >
< button
onClick = { toggleFreeze }
disabled = { loading }
className = { card . status === 'ACTIVE' ? 'btn-freeze' : 'btn-unfreeze' }
>
{ loading
? 'Processing...'
: card . status === 'ACTIVE'
? '❄️ Freeze Card'
: '✅ Unfreeze Card'
}
</ button >
< p className = "help-text" >
{ card . status === 'ACTIVE'
? 'Temporarily disable your card for security'
: 'Reactivate your card to resume using it'
}
</ p >
</ div >
) }
{ error && (
< div className = "error-message" >
{ error }
</ div >
) }
</ div >
);
}
function CardStatusBadge ({ status }) {
const statusConfig = {
ACTIVE: { icon: '✅' , color: 'green' , text: 'Active' },
FROZEN: { icon: '❄️' , color: 'blue' , text: 'Frozen' },
BLOCKED: { icon: '🚫' , color: 'red' , text: 'Blocked' }
};
const config = statusConfig [ status ] || statusConfig . ACTIVE ;
return (
< span className = { `status-badge status- ${ config . color } ` } >
{ config . icon } { config . text }
</ span >
);
}
Security Best Practices
Confirmation Dialogs
Always confirm destructive or significant actions:
async function freezeCard () {
const confirmed = await showConfirmDialog ({
title: 'Freeze Card?' ,
message: 'Your card will be temporarily disabled. You can unfreeze it anytime.' ,
confirmText: 'Freeze Card' ,
cancelText: 'Cancel'
});
if ( ! confirmed ) return ;
// Proceed with freeze
}
Audit Trail
Log all state changes for security and support:
async function logCardStateChange ( action , cardId , userId ) {
await fetch ( '/api/audit/log' , {
method: 'POST' ,
body: JSON . stringify ({
event: `card_ ${ action } ` ,
cardId ,
userId ,
timestamp: new Date (). toISOString (),
userAgent: navigator . userAgent
})
});
}
Notification
Notify users of all card state changes:
async function notifyCardStateChange ( action , userEmail ) {
await fetch ( '/api/notifications/send' , {
method: 'POST' ,
body: JSON . stringify ({
to: userEmail ,
template: `card_ ${ action } ` ,
data: {
timestamp: new Date (). toISOString (),
action: action === 'freeze' ? 'frozen' : 'unfrozen'
}
})
});
}
Freeze vs Block: When to Use Each
User initiates freeze when:
Wallet temporarily misplaced
Suspicious activity noticed
Traveling without plans to use card
Taking break from spending
Device with saved card lost
Characteristics:
✅ Reversible by user anytime
✅ No support contact needed
✅ Instant activation/deactivation
✅ Can freeze/unfreeze repeatedly
System blocks card when:
Fraud detection triggered
Multiple failed PIN attempts (3+)
Card reported lost/stolen (permanent)
Compliance/regulatory issue
Chargeback fraud detected
Characteristics:
❌ Not reversible by user
⚠️ Requires support contact
🔍 Investigation may be needed
🔄 Replacement card required
User Experience Guidelines
Status Visibility
Always display current card status prominently:
┌─────────────────────────────────────┐
│ Virtual Card │
│ •••• •••• •••• 1234 │
│ │
│ Status: [❄️ FROZEN] │
│ │
│ Last 4 transactions declined │
│ [Unfreeze Card] │
└─────────────────────────────────────┘
Action Feedback
Provide immediate visual feedback:
Freeze : Show snowflake icon, blue color, disable purchase buttons
Unfreeze : Show checkmark, green color, enable purchase buttons
Blocked : Show stop icon, red color, display support contact
State Persistence
Remember user’s last action to prevent confusion:
// Store last action in local storage
localStorage . setItem ( 'lastCardAction' , JSON . stringify ({
action: 'freeze' ,
timestamp: Date . now (),
cardId: card . id
}));
Troubleshooting
Freeze succeeds but transactions still authorize
Cause : Processing delay or cached card stateSolution :
Wait 5-10 seconds for state propagation
Verify status with GET /v1/card/status
If issue persists after 1 minute, contact support
Cannot unfreeze card (400 error)
Cause : Card may be blocked instead of frozenSolution :const card = await fetch ( '/v1/card/status' );
if ( card . status === 'BLOCKED' ) {
// Show blocked message and support contact
showBlockedCardMessage ();
}
User accidentally freezes card
Cause : No confirmation dialog implementedSolution : Always show confirmation before state changesif ( action === 'freeze' ) {
const confirmed = confirm (
'Freeze card? All transactions will be declined until you unfreeze it.'
);
if ( ! confirmed ) return ;
}
Frozen card still shows as active in UI
Cause : UI not updated after freezeSolution : Refresh card status after state changeawait fetch ( '/v1/card/freeze' , { method: 'POST' });
// Refresh status
const updatedCard = await fetch ( '/v1/card/status' );
setCard ( updatedCard );
Rate Limiting
Freeze/unfreeze operations are rate limited to prevent abuse:
Maximum 10 freeze/unfreeze operations per hour
Maximum 50 operations per day
Exceeding limits results in 429 Too Many Requests
Handle rate limiting gracefully:
async function freezeCard () {
try {
const response = await fetch ( '/v1/card/freeze' , { method: 'POST' });
if ( response . status === 429 ) {
const retryAfter = response . headers . get ( 'Retry-After' );
throw new Error (
`Too many requests. Please try again in ${ retryAfter } seconds.`
);
}
} catch ( err ) {
showError ( err . message );
}
}
Next Steps
PIN Management Implement secure PIN viewing and setting
Transaction History View and manage card transactions
Card Details Securely display full card information
API Reference Complete API documentation