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

# Virtual Cards

> Issue Visa/Mastercard virtual cards, fund them, and track spend

Issue Visa/Mastercard virtual cards for your customers, fund them, freeze/unfreeze, and track spend — regardless of which card provider is used on the backend.

<Note>
  Virtual Cards is enabled per-merchant. If it isn't enabled on your account, these endpoints return `SERVICE_NOT_ENABLED` — contact support to request access.
</Note>

<Info>
  No transaction PIN is required on these endpoints — your API key/secret is the credential for server-to-server calls, same as every other money-moving endpoint.
</Info>

## Create Cardholder

**POST** `/api/v1/virtual-cards/cardholders`

<ParamField body="first_name" type="string" required />

<ParamField body="last_name" type="string" required />

<ParamField body="email" type="string" required>
  Also used to detect an existing cardholder — calling this again with the same email returns the same cardholder rather than creating a duplicate.
</ParamField>

<ParamField body="phone" type="string" />

```bash theme={null}
curl -X POST "https://www.abcmpay.com/api/v1/virtual-cards/cardholders" \
  -H "X-Api-Key: your-public-key" \
  -H "X-Api-Secret: your-secret-key" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane@example.com"
}'
```

```json Response theme={null}
{
    "success": true,
    "cardholder_id": 501,
    "full_name": "Jane Doe",
    "email": "jane@example.com",
    "kyc_status": "PENDING"
}
```

***

## Get Cardholder

**GET** `/api/v1/virtual-cards/cardholders/{id}`

Poll this until `kyc_status` reads `APPROVED` before issuing a card — `createCard` will fail on a cardholder that hasn't passed KYC.

```json Response theme={null}
{
    "success": true,
    "cardholder_id": 501,
    "full_name": "Jane Doe",
    "email": "jane@example.com",
    "kyc_status": "APPROVED"
}
```

***

## Issue Card

**POST** `/api/v1/virtual-cards`

<ParamField body="cardholder_id" type="integer" required>
  From the [Create Cardholder](#create-cardholder) response.
</ParamField>

<ParamField body="brand" type="string" default="VISA">
  `VISA` or `MASTERCARD`.
</ParamField>

<ParamField body="label" type="string">
  Your own nickname for the card.
</ParamField>

```json Response theme={null}
{
    "success": true,
    "card_id": 9012,
    "brand": "VISA",
    "masked_pan": "4111 **** **** 1234",
    "expiry_month": 8,
    "expiry_year": 2029,
    "currency": "USD",
    "status": "active"
}
```

***

## List / Get Card

**GET** `/api/v1/virtual-cards` — paginated list of your cards.

```json Response theme={null}
{
    "success": true,
    "data": [
        {
            "card_id": 9012,
            "brand": "VISA",
            "masked_pan": "4111 **** **** 1234",
            "currency": "USD",
            "balance": 25.00,
            "status": "active",
            "created_at": "2026-02-15T12:00:00Z"
        }
    ],
    "pagination": { "current_page": 1, "total_pages": 3, "total": 47 }
}
```

**GET** `/api/v1/virtual-cards/{id}` — a single card, including its `balance`.

***

## Fund / Unload Card

**POST** `/api/v1/virtual-cards/{id}/fund`

<ParamField body="amount" type="number" required>
  USD amount to load. Your wallet is charged this amount plus your account's funding fee.
</ParamField>

**POST** `/api/v1/virtual-cards/{id}/unload` — moves funds back from the card to your wallet.

***

## Freeze / Unfreeze / Terminate

**POST** `/api/v1/virtual-cards/{id}/freeze` **POST** `/api/v1/virtual-cards/{id}/unfreeze` **POST** `/api/v1/virtual-cards/{id}/terminate`

```json Response theme={null}
{ "success": true, "message": "Card frozen." }
```

<Warning>
  Terminate is permanent — the card cannot be reactivated afterward.
</Warning>

***

## Transaction History

**GET** `/api/v1/virtual-cards/{id}/transactions`

Returns a paginated list of the card's own spend history (separate from your main wallet transaction history).
