> ## Documentation Index
> Fetch the complete documentation index at: https://docs.yativo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Virtual Cards

> Create and manage virtual payment cards for online and contactless spending

## Overview

Virtual cards are instantly issued, digital-only payment cards. Use them for online purchases, subscriptions, and contactless payments. You can create multiple virtual cards, set custom spending limits, and freeze or void them at any time.

<Note>
  Before creating a card, you must complete the [onboarding flow](/yativo-crypto/cards/onboarding) including KYC approval, terms acceptance, and wallet deployment.
</Note>

<Accordion title="Type Definitions">
  ```typescript theme={null}
  interface Card {
    card_id: string;
    yativo_card_id: string;
    display_name: string;
    type: "virtual" | "physical";
    status: "active" | "frozen" | "voided";
    last_four: string;
    expiry_month: number;
    expiry_year: number;
    spending_limit_amount: number;
    spending_limit_frequency: "daily" | "weekly" | "monthly";
    created_at: string;
  }

  interface CreateCardRequest {
    card_type?: "virtual" | "physical";
    display_name?: string;
    spending_limit_amount?: number;
    spending_limit_frequency?: "daily" | "weekly" | "monthly";
  }

  interface CardViewTokenResponse {
    secure_view_url: string;
    url: string;
    expires_at: string;
    last_four: string;
    card_type: string;
    holder_name: string;
    enabled_views: string[];
    requires_access_code: boolean;
  }
  ```
</Accordion>

***

## List Cards

Retrieve all cards associated with the authenticated account.

```
GET /yativo-card/list-cards
```

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET 'https://crypto-api.yativo.com/api/v1/yativo-card/list-cards' \
    -H 'Authorization: Bearer YOUR_API_KEY'
  ```
</RequestExample>

<ResponseExample>
  ```json Success theme={null}
  {
    "status": "success",
    "data": [
      {
        "card_id": "card_01HX9KZMB3F7VNQP8R2WDGT4E5",
        "display_name": "Online Shopping",
        "card_type": "virtual",
        "status": "active",
        "last_four": "4242",
        "spending_limit_amount": 500.00,
        "spending_limit_frequency": "monthly",
        "created_at": "2026-03-25T10:30:00Z"
      }
    ]
  }
  ```
</ResponseExample>

***

## Create Virtual Card

Issue a new virtual card. Specify a display name and optional spending limit.

```
POST /yativo-card/create-card
```

<ParamField body="card_type" type="string" required>
  Must be `"virtual"` for virtual card creation.
</ParamField>

<ParamField body="display_name" type="string" required>
  A human-readable label for the card (e.g., "Monthly Subscriptions", "Travel Expenses").
</ParamField>

<ParamField body="spending_limit_amount" type="number">
  Maximum amount the card can spend per period. Omit to set no limit.
</ParamField>

<ParamField body="spending_limit_frequency" type="string">
  The reset frequency for the spending limit. Accepted values: `daily`, `weekly`, `monthly`, `yearly`, `per_authorization`.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST 'https://crypto-api.yativo.com/api/v1/yativo-card/create-card' \
    -H 'Authorization: Bearer YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{
      "card_type": "virtual",
      "display_name": "Online Shopping",
      "spending_limit_amount": 500.00,
      "spending_limit_frequency": "monthly"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json Success theme={null}
  {
    "status": "success",
    "data": {
      "card_id": "card_01HX9KZMB3F7VNQP8R2WDGT4E5",
      "display_name": "Online Shopping",
      "card_type": "virtual",
      "status": "active",
      "last_four": "4242",
      "spending_limit_amount": 500.00,
      "spending_limit_frequency": "monthly",
      "created_at": "2026-03-25T10:30:00Z"
    }
  }
  ```
</ResponseExample>

***

## View Card Details and PIN (Secure hosted page)

Sensitive card data — the full card number (PAN), CVV, expiry, and PIN — is never returned in API responses. To display it, your backend requests a **secure view URL** from Yativo. You open that URL for the cardholder in an iframe, WebView, or browser tab. Yativo hosts the page and handles all the cryptography internally — no SDK integration required on your side.

**How it works:**

1. Your backend calls `POST /yativo-card/{yativoCardId}/cards/{cardId}/view-token`
2. You receive a `secure_view_url`
3. Open the URL for the cardholder (iframe, WebView, new tab)
4. Yativo's hosted page displays PAN, CVV, expiry and/or PIN securely

```bash theme={null}
curl -X POST 'https://crypto-api.yativo.com/api/v1/yativo-card/yc_01HX9KZMB3F7VNQP8R2WDGT4E5/cards/card_01HX9KZMB3F7VNQP8R2WDGT4E5/view-token' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "enabled_views": ["data", "pin"],
    "theme": { "accent_color": "#6366f1", "logo_url": "https://yourapp.com/logo.png" }
  }'
```

```json Response theme={null}
{
  "success": true,
  "data": {
    "secure_view_url": "https://crypto-api.yativo.com/api/v1/yativo-card/view/eyJhbGci...",
    "expires_at": "2026-03-26T12:01:00Z",
    "last_four": "4242",
    "enabled_views": ["data", "pin"],
    "requires_access_code": false
  }
}
```

<Warning>
  Always request a fresh URL immediately before showing card details. Never cache or reuse a previous `secure_view_url`.
</Warning>

<Card title="Full integration guide" icon="window" href="/yativo-crypto/cards/secure-display">
  Backend proxy pattern, iframe embedding, access code flow, theming options, React/Vue/Vanilla JS examples, and CSP requirements.
</Card>

***

## Set Card PIN

<Note>
  The `pin_set` field in the view-token response tells you whether Yativo has received a `physical.card.pin.changed` webhook for this card. Use it to decide whether to prompt the cardholder to set their PIN — the same `enabled_views: ["pin"]` view also handles PIN **changes**.
</Note>

Card PINs are set and changed through Yativo's **hosted secure page** — the cardholder types their PIN directly inside a sandboxed iframe. The PIN never touches your backend.

**How to show the PIN-setup page:**

1. Call `POST /yativo-card/{yativoCardId}/cards/{cardId}/view-token` with `enabled_views: ["pin"]`
2. Open the returned `secure_view_url` in an `<iframe>` or WebView
3. The cardholder enters and confirms their 4-digit PIN inside the hosted page
4. Once saved, `pin_set` becomes `true` on the card record — card details can now be displayed

```bash theme={null}
curl -X POST 'https://crypto-api.yativo.com/api/v1/yativo-card/yc_01HX9KZMB3F7VNQP8R2WDGT4E5/cards/card_01HX9KZMB3F7VNQP8R2WDGT4E5/view-token' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{ "enabled_views": ["pin"] }'
```

```json Response theme={null}
{
  "success": true,
  "data": {
    "secure_view_url": "https://crypto-api.yativo.com/api/v1/yativo-card/view/eyJhbGci...",
    "pin_set": false,
    "enabled_views": ["pin"],
    "expires_at": "2026-05-18T12:05:00.000Z"
  }
}
```

Embed the URL:

```html theme={null}
<iframe
  src="https://crypto-api.yativo.com/api/v1/yativo-card/view/eyJhbGci..."
  title="Set Card PIN"
  width="420" height="520"
  style="border:0; border-radius:16px;"
  allow="clipboard-read; clipboard-write">
</iframe>
```

<Card title="Setting a Card PIN" icon="lock" href="/yativo-crypto/cards/set-pin">
  Complete flow for virtual and physical cards — PSE iframe, brand theming, `pin_set` monitoring, and webhook confirmation.
</Card>

***

## Freeze a Card

Temporarily suspend a card. All transactions on a frozen card will be declined until unfrozen.

```
POST /yativo-card/cards/{cardId}/freeze
```

<ParamField path="cardId" type="string" required>
  The card ID to freeze.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST 'https://crypto-api.yativo.com/api/v1/yativo-card/cards/card_01HX9KZMB3F7VNQP8R2WDGT4E5/freeze' \
    -H 'Authorization: Bearer YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{}'
  ```
</RequestExample>

<ResponseExample>
  ```json Success theme={null}
  {
    "status": "success",
    "data": {
      "card_id": "card_01HX9KZMB3F7VNQP8R2WDGT4E5",
      "status": "frozen",
      "frozen_at": "2026-03-25T11:00:00Z"
    }
  }
  ```
</ResponseExample>

***

## Unfreeze a Card

Re-activate a frozen card.

```
POST /yativo-card/cards/{cardId}/unfreeze
```

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST 'https://crypto-api.yativo.com/api/v1/yativo-card/cards/card_01HX9KZMB3F7VNQP8R2WDGT4E5/unfreeze' \
    -H 'Authorization: Bearer YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{}'
  ```
</RequestExample>

<ResponseExample>
  ```json Success theme={null}
  {
    "status": "success",
    "data": {
      "card_id": "card_01HX9KZMB3F7VNQP8R2WDGT4E5",
      "status": "active",
      "unfrozen_at": "2026-03-25T11:05:00Z"
    }
  }
  ```
</ResponseExample>

***

## Void a Card

Permanently cancel a card. This action is irreversible. A voided card cannot be reactivated.

```
POST /yativo-card/cards/{cardId}/void
```

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST 'https://crypto-api.yativo.com/api/v1/yativo-card/cards/card_01HX9KZMB3F7VNQP8R2WDGT4E5/void' \
    -H 'Authorization: Bearer YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{}'
  ```
</RequestExample>

<ResponseExample>
  ```json Success theme={null}
  {
    "status": "success",
    "data": {
      "card_id": "card_01HX9KZMB3F7VNQP8R2WDGT4E5",
      "status": "voided",
      "voided_at": "2026-03-25T11:10:00Z"
    }
  }
  ```
</ResponseExample>

<Warning>
  Voiding a card is permanent. If you only need to temporarily stop spending, use [freeze](#freeze-a-card) instead.
</Warning>

***

## Get User Profile

Retrieve the card account profile for a given Yativo Card ID.

```
GET /yativo-card/{yativoCardId}/profile
```

<ParamField path="yativoCardId" type="string" required>
  The Yativo Card account ID.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET 'https://crypto-api.yativo.com/api/v1/yativo-card/yc_01HX9KZMB3F7VNQP8R2WDGT4E5/profile' \
    -H 'Authorization: Bearer YOUR_API_KEY'
  ```
</RequestExample>

<ResponseExample>
  ```json Success theme={null}
  {
    "status": "success",
    "data": {
      "yativo_card_id": "yc_01HX9KZMB3F7VNQP8R2WDGT4E5",
      "email": "user@example.com",
      "first_name": "Jane",
      "last_name": "Doe",
      "kyc_status": "approved",
      "terms_accepted": true,
      "wallet_deployed": true,
      "created_at": "2026-03-25T10:00:00Z"
    }
  }
  ```
</ResponseExample>

***

## Card Status Reference

| Status    | Description                                                   |
| --------- | ------------------------------------------------------------- |
| `active`  | Card is in good standing and can be used for transactions.    |
| `frozen`  | Card is temporarily suspended. Transactions will be declined. |
| `voided`  | Card has been permanently cancelled. Cannot be reactivated.   |
| `pending` | Card is being provisioned. Usually resolves within seconds.   |

***

## Sandbox Testing

<Note>
  Replace `YOUR_SANDBOX_TOKEN` with a token obtained by authenticating against `https://crypto-sandbox.yativo.com/api/v1/`. See [Sandbox Overview](/sandbox/overview).
</Note>

### Create a Virtual Card (Sandbox)

<CodeGroup>
  ```bash cURL (Sandbox) theme={null}
  curl -X POST 'https://crypto-sandbox.yativo.com/api/v1/yativo-card/create-card' \
    -H 'Authorization: Bearer YOUR_SANDBOX_TOKEN' \
    -H 'Content-Type: application/json' \
    -d '{
      "card_type": "virtual",
      "display_name": "Sandbox Test Card",
      "spending_limit_amount": 100.00,
      "spending_limit_frequency": "monthly"
    }'
  ```

  ```typescript TypeScript SDK (Sandbox) theme={null}
  import { YativoSDK } from '@yativo/crypto-sdk';

  const sdk = new YativoSDK({
    baseURL: 'https://crypto-sandbox.yativo.com/api/v1/',
    apiKey: 'YOUR_SANDBOX_API_KEY',
    apiSecret: 'YOUR_SANDBOX_API_SECRET',
  });

  const card = await sdk.cards.create({
    card_type: 'virtual',
    display_name: 'Sandbox Test Card',
    spending_limit_amount: 100.00,
    spending_limit_frequency: 'monthly',
  });
  console.log('Card ID:', card.data.card_id);
  ```
</CodeGroup>

### List Cards (Sandbox)

<CodeGroup>
  ```bash cURL (Sandbox) theme={null}
  curl -X GET 'https://crypto-sandbox.yativo.com/api/v1/yativo-card/list-cards' \
    -H 'Authorization: Bearer YOUR_SANDBOX_TOKEN'
  ```

  ```typescript TypeScript SDK (Sandbox) theme={null}
  import { YativoSDK } from '@yativo/crypto-sdk';

  const sdk = new YativoSDK({
    baseURL: 'https://crypto-sandbox.yativo.com/api/v1/',
    apiKey: 'YOUR_SANDBOX_API_KEY',
    apiSecret: 'YOUR_SANDBOX_API_SECRET',
  });

  const cards = await sdk.cards.list();
  console.log('Cards:', cards.data);
  ```
</CodeGroup>
