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

# Card Lifecycle Management

> Control card status with freeze, unfreeze, and state management operations

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

<Info>
  Freezing a card is a temporary, reversible action. Users can freeze and unfreeze their cards as many times as needed.
</Info>

## Card States

Understanding card states is essential for proper lifecycle management:

<CardGroup cols={3}>
  <Card title="Active" icon="circle-check" color="#16a34a">
    Card is operational and can process transactions
  </Card>

  <Card title="Frozen" icon="snowflake" color="#3b82f6">
    Card is temporarily disabled by user
  </Card>

  <Card title="Blocked" icon="ban" color="#dc2626">
    Card is permanently disabled by system
  </Card>
</CardGroup>

### State Transitions

```mermaid theme={null}
stateDiagram-v2
    [*] --> Active: Card Ordered
    Active --> Frozen: User Freeze
    Frozen --> Active: User Unfreeze
    Active --> Blocked: System Block (Fraud/Compliance)
    Frozen --> Blocked: System Block (Fraud/Compliance)
    Blocked --> [*]: Card Replaced
```

### State Details

<AccordionGroup>
  <Accordion title="Active" icon="check-circle">
    **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
  </Accordion>

  <Accordion title="Frozen" icon="snowflake">
    **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
  </Accordion>

  <Accordion title="Blocked" icon="ban">
    **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
  </Accordion>
</AccordionGroup>

## Freezing a Card

Temporarily disable a card to prevent unauthorized transactions.

### When to Freeze

<Check>Wallet misplaced (not confirmed lost)</Check>
<Check>Suspicious transaction notification</Check>
<Check>Traveling and not using card</Check>
<Check>Taking a break from spending</Check>
<Check>Device with saved card details lost</Check>

### API Request

<CodeGroup>
  ```javascript JavaScript/Node.js theme={null}
  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
  }
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://dev.api.baanx.com/v1/card/freeze',
      headers={
          'X-Client-ID': 'your_client_id',
          'Authorization': f'Bearer {user_access_token}'
      }
  )

  result = response.json()

  if result.get('success'):
      print('Card frozen successfully')
  ```

  ```bash cURL theme={null}
  curl -X POST https://dev.api.baanx.com/v1/card/freeze \
    -H "X-Client-ID: your_client_id" \
    -H "Authorization: Bearer YOUR_USER_ACCESS_TOKEN"
  ```
</CodeGroup>

### Response

<Tabs>
  <Tab title="Success (200)">
    ```json theme={null}
    {
      "success": true
    }
    ```

    Card has been frozen. All transaction attempts will now be declined until the card is unfrozen.
  </Tab>

  <Tab title="Error (400)">
    ```json theme={null}
    {
      "message": "Card is already frozen",
      "code": "INVALID_STATE"
    }
    ```

    Card is already in frozen state. No action needed.
  </Tab>

  <Tab title="Error (404)">
    ```json theme={null}
    {
      "message": "Card not found"
    }
    ```

    User doesn't have a card. Direct them to order a card first.
  </Tab>
</Tabs>

### Implementation Example

<CodeGroup>
  ```javascript React Component theme={null}
  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>
    );
  }
  ```

  ```python Flask Backend theme={null}
  from flask import jsonify, request
  import requests

  @app.route('/api/card/freeze', methods=['POST'])
  def freeze_card():
      access_token = request.headers.get('Authorization').split(' ')[1]
      client_id = app.config['CLIENT_ID']

      try:
          response = requests.post(
              'https://dev.api.baanx.com/v1/card/freeze',
              headers={
                  'X-Client-ID': client_id,
                  'Authorization': f'Bearer {access_token}'
              }
          )

          if not response.ok:
              error = response.json()
              return jsonify({'error': error.get('message')}), response.status_code

          result = response.json()

          return jsonify({
              'success': True,
              'message': 'Card frozen successfully'
          })

      except Exception as e:
          return jsonify({'error': str(e)}), 500
  ```
</CodeGroup>

## Unfreezing a Card

Reactivate a frozen card to resume normal operations.

### When to Unfreeze

<Check>Wallet found</Check>
<Check>Suspicious activity resolved</Check>
<Check>Ready to use card again</Check>
<Check>Returned from travel</Check>

### API Request

<CodeGroup>
  ```javascript JavaScript/Node.js theme={null}
  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');
  }
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://dev.api.baanx.com/v1/card/unfreeze',
      headers={
          'X-Client-ID': 'your_client_id',
          'Authorization': f'Bearer {user_access_token}'
      }
  )

  result = response.json()

  if result.get('success'):
      print('Card unfrozen - ready to use')
  ```

  ```bash cURL theme={null}
  curl -X POST https://dev.api.baanx.com/v1/card/unfreeze \
    -H "X-Client-ID: your_client_id" \
    -H "Authorization: Bearer YOUR_USER_ACCESS_TOKEN"
  ```
</CodeGroup>

### Response

<Tabs>
  <Tab title="Success (200)">
    ```json theme={null}
    {
      "success": true
    }
    ```

    Card has been unfrozen and is now active. Transactions will be authorized normally.
  </Tab>

  <Tab title="Error (400)">
    ```json theme={null}
    {
      "message": "Card is not frozen",
      "code": "INVALID_STATE"
    }
    ```

    Card is not in frozen state (may be active or blocked). Check current status.
  </Tab>

  <Tab title="Error (404)">
    ```json theme={null}
    {
      "message": "Card not found"
    }
    ```

    User doesn't have a card.
  </Tab>
</Tabs>

### Implementation Example

<CodeGroup>
  ```javascript React Component theme={null}
  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>
    );
  }
  ```

  ```python Flask Backend theme={null}
  from flask import jsonify, request
  import requests

  @app.route('/api/card/unfreeze', methods=['POST'])
  def unfreeze_card():
      access_token = request.headers.get('Authorization').split(' ')[1]
      client_id = app.config['CLIENT_ID']

      try:
          response = requests.post(
              'https://dev.api.baanx.com/v1/card/unfreeze',
              headers={
                  'X-Client-ID': client_id,
                  'Authorization': f'Bearer {access_token}'
              }
          )

          if not response.ok:
              error = response.json()
              return jsonify({'error': error.get('message')}), response.status_code

          result = response.json()

          return jsonify({
              'success': True,
              'message': 'Card unfrozen successfully'
          })

      except Exception as e:
          return jsonify({'error': str(e)}), 500
  ```
</CodeGroup>

## Complete Card Control Component

Here's a comprehensive component that handles all card states:

<CodeGroup>
  ```javascript React theme={null}
  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>
    );
  }
  ```
</CodeGroup>

## Security Best Practices

### Confirmation Dialogs

Always confirm destructive or significant actions:

```javascript theme={null}
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:

```javascript theme={null}
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:

```javascript theme={null}
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

<Tabs>
  <Tab title="Freeze (User Controlled)">
    **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
  </Tab>

  <Tab title="Block (System Controlled)">
    **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
  </Tab>
</Tabs>

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

```javascript theme={null}
// Store last action in local storage
localStorage.setItem('lastCardAction', JSON.stringify({
  action: 'freeze',
  timestamp: Date.now(),
  cardId: card.id
}));
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Freeze succeeds but transactions still authorize">
    **Cause**: Processing delay or cached card state

    **Solution**:

    * Wait 5-10 seconds for state propagation
    * Verify status with `GET /v1/card/status`
    * If issue persists after 1 minute, contact support
  </Accordion>

  <Accordion title="Cannot unfreeze card (400 error)">
    **Cause**: Card may be blocked instead of frozen

    **Solution**:

    ```javascript theme={null}
    const card = await fetch('/v1/card/status');
    if (card.status === 'BLOCKED') {
      // Show blocked message and support contact
      showBlockedCardMessage();
    }
    ```
  </Accordion>

  <Accordion title="User accidentally freezes card">
    **Cause**: No confirmation dialog implemented

    **Solution**: Always show confirmation before state changes

    ```javascript theme={null}
    if (action === 'freeze') {
      const confirmed = confirm(
        'Freeze card? All transactions will be declined until you unfreeze it.'
      );
      if (!confirmed) return;
    }
    ```
  </Accordion>

  <Accordion title="Frozen card still shows as active in UI">
    **Cause**: UI not updated after freeze

    **Solution**: Refresh card status after state change

    ```javascript theme={null}
    await fetch('/v1/card/freeze', { method: 'POST' });
    // Refresh status
    const updatedCard = await fetch('/v1/card/status');
    setCard(updatedCard);
    ```
  </Accordion>
</AccordionGroup>

## Rate Limiting

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

Handle rate limiting gracefully:

```javascript theme={null}
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

<CardGroup cols={2}>
  <Card title="PIN Management" icon="lock" href="/guides/card/pin-operations">
    Implement secure PIN viewing and setting
  </Card>

  <Card title="Transaction History" icon="receipt" href="/guides/card/transactions">
    View and manage card transactions
  </Card>

  <Card title="Card Details" icon="credit-card" href="/guides/card/pin-operations#viewing-card-details">
    Securely display full card information
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/card/freeze">
    Complete API documentation
  </Card>
</CardGroup>
