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

# Virtual Cards (coming soon)

This page outlines the `Card` object that will be used to issue and manage virtual cards through Confido Legal.

## The Card Object

```graphql theme={"system"}
type Card {
  id: string
  authorizationControls?: AuthorizationControls
  bankAccount: BankAccount
  billingAddress: Address
  bin: string
  cardholderName: CardholderName
  client?: Client
  createdOn: Date
  expMonth: string
  expYear: string
  lastFour: string
  matter?: Matter
  nickname?: string
  status: string
  vendor?: Vendor
}
```

**AuthorizationControls**

```graphql theme={"system"}
type AuthorizationControls {
  merchantAcceptorIds: AllowBlockList
  merchantCategoryCode: AllowBlockList
  merchantCountry: AllowBlockList
  usage: UsageControls
}

type AllowBlockList {
  allowed: [String]
  blocked: [String]
}

type UsageControls {
  category: 'single_use' | 'multi_use'
  multiUse?: MultiUseControls
  singleUse?: SingleUseControls
}

type MultiUseControls {
  spendingLimits: SpendingLimit[]
}

type SpendingLimit {
  interval: 'all_time' | 'per_transaction' | 'per_day' | 'per_week' | 'per_month'
  merchantCategoryCodes?: [String]
  settlementAmount: Int
}

type SingleUseControls {
  settlementAmount: SingleUseSettlementAmount
}

type SingleUseSettlementAmount {
  comparison: 'equals' | 'less_than_or_equals'
  value: Int
}
```

## Creating a Card

The `cardCreate` mutation issues a new virtual card. Call it with the Firm API token.

```graphql theme={"system"}
mutation CardCreate($input: CardCreateInput!) {
  cardCreate(input: $input) {
    id
    bin
    cardholderName
    createdOn
    expMonth
    expYear
    lastFour
    nickname
    status
  }
}
```

**Input**

* **`authorizationControls`** — restrictions on where and how the card can be used (nullable)
* **`bankAccountId`** — the ID of the bank account the card is funded from
* **`billingAddress`** — the billing address associated with the card, defaults to the firm address (nullable)
* **`cardholderName`** — the name of the cardholder, defaults to the firm name (nullable)
* **`clientId`** — the ID of the client to associate with the card (nullable)
* **`matterId`** — the ID of the matter to associate with the card (nullable)
* **`nickname`** — an optional nickname for the card (nullable)
* **`vendorId`** — the ID of the vendor to associate with the card (nullable)

## Update a Card

The `cardUpdate` mutation updates an existing virtual card. Call it with the Firm API token.

```graphql theme={"system"}
mutation CardUpdate($input: CardUpdateInput!) {
  cardUpdate(input: $input) {
    id
    bin
    cardholderName
    createdOn
    expMonth
    expYear
    lastFour
    nickname
    status
  }
}
```

**Input**

* **`id`** — the ID of the card to update
* **`authorizationControls`** — restrictions on where and how the card can be used (nullable)
* **`billingAddress`** — the billing address associated with the card (nullable)
* **`clientId`** — the ID of the client to associate with the card (nullable)
* **`matterId`** — the ID of the matter to associate with the card (nullable)
* **`nickname`** — an optional nickname for the card (nullable)
* **`status`** — the status of the card (nullable)
* **`vendorId`** — the ID of the vendor to associate with the card (nullable)

## Viewing Card Details

Sensitive card details (PAN, CVV, and expiration) are never returned directly from the API. To view a card, mint a short-lived token from your server, then open Confido's hosted card page or embed it in an iframe. Card data is rendered on Confido's hosted page, so your servers stay out of PCI scope for card display.

### High level flow

<Steps>
  <Step title="Mint a card view token from your server" />

  <Step title="Open the hosted card page or embed an iframe using the token" />

  <Step title="Mint a new token when the previous one expires" />
</Steps>

### 1. Create a token

Call `cardDetailsTokenCreate` with the Firm API token and the card ID:

```graphql theme={"system"}
mutation CardDetailsTokenCreate($input: CardDetailsTokenCreateInput!) {
  cardDetailsTokenCreate(input: $input) {
    token
    expiresAt
  }
}
```

**Input**

* **`cardId`** — the ID of the card to view

**Response**

* **`token`** — a short-lived token used to access the card details page
* **`expiresAt`** — when the token expires (one hour after creation)

Keep the Firm API token on your server. Only the returned `token` should be sent to the browser.

### 2. View the card

| Environment | Base URL                               |
| ----------- | -------------------------------------- |
| Sandbox     | `https://pay.sandbox.confidolegal.com` |
| Production  | `https://pay.confidolegal.com`         |

**Hosted page**

Redirect the user (or open a new tab) to the card details page with the token as a query parameter:

```
https://pay.sandbox.confidolegal.com/card?token=TOKEN
```

**iframe**

Embed the card details iframe in your application:

```html theme={"system"}
<iframe
  id="card-display"
  title="Virtual card"
  src="https://pay.sandbox.confidolegal.com/card/iframe?token=TOKEN"
  style="border: none; width: 100%; min-height: 320px;"
></iframe>
```

Register your application's parent-page origin as a [trusted domain](/docs/hosted-fields/trusted-domains) when embedding the iframe. Required in sandbox and production.

### Notes

* Tokens expire after **one hour**. When a token expires, call `cardDetailsTokenCreate` again and update the page URL or iframe `src`.
* Do not cache or log full card details. Treat the token as sensitive while it is valid.
* Your application should never collect or store PAN or CVV from the displayed card.
