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

# Generate Card Details Token

> Generate a secure token for displaying sensitive card details through an image-based display

## Overview

Generates a time-limited secure token that allows you to display sensitive card information (full PAN, CVV, expiry date) as an image without ever handling this data directly in your application. The token provides access to a secure image URL that renders card details in a PCI-compliant manner.

<Info>
  **PCI Compliance Made Easy**

  This endpoint eliminates PCI compliance burden by returning card details as a secure image. Your application never touches or stores the actual card details.
</Info>

## Authentication

This endpoint requires authentication via Bearer token:

```bash theme={null}
Authorization: Bearer YOUR_ACCESS_TOKEN
```

## Request

### Headers

<ParamField header="x-client-key" type="string" required>
  Your public API client key
</ParamField>

<ParamField header="x-us-env" type="boolean" default={false}>
  Set to `true` to route requests to the US backend environment
</ParamField>

<ParamField header="Authorization" type="string" required>
  Bearer token for authentication
</ParamField>

### Body

<Note>
  The request body is **optional**. If omitted, default styling will be applied to the card image.
</Note>

<ParamField body="customCss" type="object">
  Customize the visual appearance of the card details image to match your brand

  <Expandable title="customCss properties">
    <ParamField body="customCss.cardBackgroundColor" type="string" default="#000000">
      Background color of the card image

      **Example:** `#1A1A1A`, `#2563EB`
    </ParamField>

    <ParamField body="customCss.cardTextColor" type="string" default="#FFFFFF">
      Text color for card information

      **Important:** Avoid using the same color as `cardBackgroundColor` for readability

      **Example:** `#FFFFFF`, `#F3F4F6`
    </ParamField>

    <ParamField body="customCss.panBackgroundColor" type="string" default="#EFEFEF">
      Background color for the PAN number display area

      **Example:** `#F9FAFB`, `#E5E7EB`
    </ParamField>

    <ParamField body="customCss.panTextColor" type="string" default="#000000">
      Text color for PAN number

      **Important:** Avoid using the same color as `panBackgroundColor` for readability

      **Example:** `#000000`, `#111827`
    </ParamField>
  </Expandable>
</ParamField>

### Request Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://dev.api.baanx.com/v1/card/details/token \
    -H "x-client-key: YOUR_CLIENT_KEY" \
    -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "customCss": {
        "cardBackgroundColor": "#000000",
        "cardTextColor": "#FFFFFF",
        "panBackgroundColor": "#EFEFEF",
        "panTextColor": "#000000"
      }
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://dev.api.baanx.com/v1/card/details/token', {
    method: 'POST',
    headers: {
      'x-client-key': 'YOUR_CLIENT_KEY',
      'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      customCss: {
        cardBackgroundColor: '#000000',
        cardTextColor: '#FFFFFF',
        panBackgroundColor: '#EFEFEF',
        panTextColor: '#000000'
      }
    })
  });

  const data = await response.json();
  console.log('Card image URL:', data.imageUrl);
  ```

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

  url = "https://dev.api.baanx.com/v1/card/details/token"
  headers = {
      "x-client-key": "YOUR_CLIENT_KEY",
      "Authorization": "Bearer YOUR_ACCESS_TOKEN",
      "Content-Type": "application/json"
  }
  payload = {
      "customCss": {
          "cardBackgroundColor": "#000000",
          "cardTextColor": "#FFFFFF",
          "panBackgroundColor": "#EFEFEF",
          "panTextColor": "#000000"
      }
  }

  response = requests.post(url, headers=headers, json=payload)
  data = response.json()
  print(f"Card image URL: {data['imageUrl']}")
  ```

  ```typescript TypeScript theme={null}
  interface CardDetailsTokenRequest {
    customCss?: {
      cardBackgroundColor?: string;
      cardTextColor?: string;
      panBackgroundColor?: string;
      panTextColor?: string;
    };
  }

  interface CardDetailsTokenResponse {
    token: string;
    imageUrl: string;
  }

  const generateCardDetailsToken = async (
    config?: CardDetailsTokenRequest
  ): Promise<CardDetailsTokenResponse> => {
    const response = await fetch('https://dev.api.baanx.com/v1/card/details/token', {
      method: 'POST',
      headers: {
        'x-client-key': 'YOUR_CLIENT_KEY',
        'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
        'Content-Type': 'application/json'
      },
      body: config ? JSON.stringify(config) : undefined
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    return await response.json();
  };
  ```
</CodeGroup>

## Response

### Success Response

<ResponseField name="token" type="string">
  Secure, time-limited token (UUID format)

  **Lifetime:** \~10 minutes

  **Usage:** Single-use token that becomes invalid after the image is accessed
</ResponseField>

<ResponseField name="imageUrl" type="string">
  URL that renders card details as a secure image

  **Usage:** Display card details by using this URL as the `src` attribute of an `<img>` tag

  **Format:** `<HOST>/details-image?token={token}`

  **Security:** Treat this URL as highly sensitive. Do not log or store it.
</ResponseField>

<ResponseExample>
  ```json 200 - Success theme={null}
  {
    "token": "100a99cf-f4d3-4fa1-9be9-2e9828b20ebb",
    "imageUrl": "https://cards.baanx.com/details-image?token=100a99cf-f4d3-4fa1-9be9-2e9828b20ebb"
  }
  ```
</ResponseExample>

## Error Responses

<ResponseExample>
  ```json 401 - Unauthorized theme={null}
  {
    "message": "Not authenticated"
  }
  ```

  ```json 403 - Forbidden theme={null}
  {
    "message": "Not authorized"
  }
  ```

  ```json 404 - Card Not Found theme={null}
  {
    "message": "Card not found"
  }
  ```

  ```json 422 - Validation Error theme={null}
  {
    "message": "Validation error",
    "errors": [
      {
        "field": "customCss.cardBackgroundColor",
        "message": "Invalid hex color format"
      }
    ]
  }
  ```

  ```json 498 - Invalid Client Key theme={null}
  {
    "message": "Invalid client key"
  }
  ```

  ```json 499 - Missing Client Key theme={null}
  {
    "message": "Missing client key"
  }
  ```

  ```json 500 - Internal Server Error theme={null}
  {
    "message": "Internal server error"
  }
  ```
</ResponseExample>

## Integration Method

Display card details as a secure image without interactive elements.

### Basic Implementation

```javascript theme={null}
const { imageUrl } = await generateCardDetailsToken({
  customCss: {
    cardBackgroundColor: '#000000',
    cardTextColor: '#FFFFFF',
    panBackgroundColor: '#EFEFEF',
    panTextColor: '#000000'
  }
});

const img = document.createElement('img');
img.src = imageUrl;
img.alt = 'Card Details';
img.style.maxWidth = '100%';
img.style.borderRadius = '12px';

document.getElementById('card-image-container').appendChild(img);
```

### React Component Example

```typescript theme={null}
import { useState } from 'react';

export function CardDetailsImage() {
  const [imageUrl, setImageUrl] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const handleViewCard = async () => {
    setLoading(true);
    setError(null);

    try {
      const response = await fetch('https://dev.api.baanx.com/v1/card/details/token', {
        method: 'POST',
        headers: {
          'x-client-key': 'YOUR_CLIENT_KEY',
          'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          customCss: {
            cardBackgroundColor: '#000000',
            cardTextColor: '#FFFFFF',
            panBackgroundColor: '#EFEFEF',
            panTextColor: '#000000'
          }
        })
      });

      if (!response.ok) {
        throw new Error('Failed to generate card details token');
      }

      const data = await response.json();
      setImageUrl(data.imageUrl);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'An error occurred');
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <button onClick={handleViewCard} disabled={loading}>
        {loading ? 'Loading...' : 'View Card Details'}
      </button>

      {error && <div className="error">{error}</div>}

      {imageUrl && (
        <div className="card-image-container">
          <img
            src={imageUrl}
            alt="Card Details"
            style={{ maxWidth: '100%', borderRadius: '12px' }}
          />
          <button onClick={() => setImageUrl(null)}>Close</button>
        </div>
      )}
    </div>
  );
}
```

<Warning>
  **Security Note**

  Image URLs contain sensitive card information. Always:

  * Use HTTPS only
  * Never log or store the imageUrl
  * Display in secure contexts only
  * Clear the image from DOM when user is done viewing
</Warning>

## Customization Examples

### Dark Mode Theme

```json theme={null}
{
  "customCss": {
    "cardBackgroundColor": "#1F2937",
    "cardTextColor": "#F9FAFB",
    "panBackgroundColor": "#374151",
    "panTextColor": "#F3F4F6"
  }
}
```

### Light Mode Theme

```json theme={null}
{
  "customCss": {
    "cardBackgroundColor": "#FFFFFF",
    "cardTextColor": "#111827",
    "panBackgroundColor": "#F3F4F6",
    "panTextColor": "#1F2937"
  }
}
```

### Brand Colors

```json theme={null}
{
  "customCss": {
    "cardBackgroundColor": "#2563EB",
    "cardTextColor": "#FFFFFF",
    "panBackgroundColor": "#DBEAFE",
    "panTextColor": "#1E40AF"
  }
}
```

## Security Considerations

<Warning>
  **Token Lifetime and Single-Use**

  * Tokens expire after \~10 minutes
  * Tokens are single-use and become invalid after first access
  * Generate a new token each time the user wants to view card details
  * Never store or cache tokens
</Warning>

<Note>
  **PCI Compliance**

  By using this endpoint, you avoid PCI compliance requirements as sensitive card data is delivered as an image. Your servers and frontend code never handle the actual card details.
</Note>

<Info>
  **URL Security**

  * Treat `imageUrl` as highly sensitive data
  * Don't log or store these URLs
  * Use HTTPS only
  * Display only in authenticated, secure contexts
</Info>

## Best Practices

### Error Handling

```typescript theme={null}
async function showCardDetails() {
  try {
    const { imageUrl } = await generateCardDetailsToken({
      customCss: {
        cardBackgroundColor: '#000000',
        cardTextColor: '#FFFFFF',
        panBackgroundColor: '#EFEFEF',
        panTextColor: '#000000'
      }
    });

    const img = document.createElement('img');
    img.src = imageUrl;
    img.alt = 'Card Details';
    img.style.maxWidth = '100%';
    document.getElementById('card-container').appendChild(img);

  } catch (error) {
    if (error.response?.status === 404) {
      alert('No card found. Please order a card first.');
    } else if (error.response?.status === 401) {
      alert('Session expired. Please log in again.');
    } else if (error.response?.status === 422) {
      alert('Invalid styling parameters. Please check your customCss values.');
    } else {
      alert('Failed to load card details. Please try again.');
    }
  }
}
```

### Cleanup After Viewing

```typescript theme={null}
function createCardViewer() {
  let currentImage: HTMLImageElement | null = null;

  async function showCard() {
    const { imageUrl } = await generateCardDetailsToken();

    currentImage = document.createElement('img');
    currentImage.src = imageUrl;
    currentImage.alt = 'Card Details';
    document.getElementById('card-container').appendChild(currentImage);
  }

  function hideCard() {
    if (currentImage) {
      currentImage.remove();
      currentImage = null;
    }
  }

  return { showCard, hideCard };
}

const cardViewer = createCardViewer();
```

## Common Issues and Solutions

<AccordionGroup>
  <Accordion title="Token Expired">
    **Symptom:** Image fails to load with "Invalid or expired token" error

    **Cause:** Token has expired (>10 minutes old) or was already used

    **Solution:** Generate a new token. Never reuse or cache tokens.
  </Accordion>

  <Accordion title="Colors Not Readable">
    **Symptom:** Text is difficult to read on the card image

    **Cause:** Text color and background color are too similar

    **Solution:** Ensure sufficient contrast between text and background colors. Avoid using the same hex value for both.
  </Accordion>

  <Accordion title="Image Not Displaying">
    **Symptom:** Image element shows broken image icon

    **Cause:** Token may be invalid, expired, or network issue

    **Solution:**

    ```javascript theme={null}
    const img = document.createElement('img');
    img.onerror = () => {
      console.error('Failed to load card image');
      alert('Unable to display card details. Please try again.');
    };
    img.src = imageUrl;
    ```
  </Accordion>

  <Accordion title="422 Validation Error">
    **Symptom:** Request fails with 422 status code

    **Cause:** Invalid customCss parameters (e.g., malformed hex colors)

    **Solution:** Ensure all color values are valid 6-digit hex codes starting with #. Example: `#1A1A1A`, not `1A1A1A` or `#1A1A`
  </Accordion>
</AccordionGroup>

## Related Endpoints

* `GET /v1/card/status` - Get basic card information before generating token
* `POST /v1/card/pin/token` - Generate token to view card PIN
* `POST /v1/card/set-pin/token` - Generate token to set/change card PIN
* `POST /v1/card/freeze` - Temporarily disable card
* `POST /v1/card/order` - Order a new card
