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

# Cards

> Issue virtual Visa cards backed by stablecoin collateral, with support for Google Wallet and 3DS.

This guide covers the full lifecycle of a virtual card: from issuance and funding, through per-card configuration and spending controls, to fraud protection and transaction visibility. All operations are available both via the API (API key auth) and the CryptoMate Portal.

## Overview

**Cards** is a virtual prepaid card product powered by cryptocurrency collateral. Designed for businesses, it uses **stablecoins on Polygon** as the backing asset: each card is linked to a stablecoin wallet, and funds are automatically converted to dollars at a 1:1 ratio, making integration with conventional payment networks seamless.

## Card specifications

* **Brand:** Visa
* **Acceptance:** Google Wallet and e-commerce platforms
* **Security:** Protected by **3DS** to mitigate fraud

## Operational models

<Columns cols={2}>
  <Card title="Top Up" icon="wallet">
    Users load funds directly onto the card through a dedicated deposit wallet created exclusively for this purpose.
  </Card>

  <Card title="External authorization" icon="shield-check">
    Your systems integrate via webhooks: for each transaction you have **1,200 ms** to authorize or reject it based on your own approval logic.
  </Card>
</Columns>

## How it works

Each virtual card is a **prepaid Visa card backed by stablecoin collateral**. At the account level, a single **holding wallet** on the Polygon network holds all funds. When a purchase is made, the holding wallet balance is verified and the appropriate amount is debited.

```
Holding wallet (USDC, Polygon)
    └── Virtual Card A  ── purchase → authorization → settled
    └── Virtual Card B  ── purchase → authorization → settled
    └── Virtual Card C  ...
```

Cards are issued against a card pack. Each company has a maximum number of active cards based on their contracted product. You can check available capacity via [Get contracted product](/api-reference/management/contracted-products/get-contracted-product).

***

## Creating a card

Use [Create virtual card](/api-reference/cards/virtual-cards/create-card) to issue a new card.

The two required decisions at creation time are:

### Approval method

| Value     | How purchases are approved                                                                                                                                                  |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `TOPUP`   | The cardholder pre-loads funds onto the card's individual deposit wallet. Purchases are auto-approved against that balance.                                                 |
| `WEBHOOK` | Each purchase triggers a real-time webhook to your endpoint. You have **1,200 ms** to respond with `"00"` / `"SUCCESS"` to approve or `"05"` to decline. Timeout = decline. |

<Note>
  The `approval_method` cannot be changed after card creation. If the wrong method is set, delete the card and reissue.
</Note>

### Spending limits

Set `daily_limit`, `weekly_limit`, and `monthly_limit` (in USD) at creation. These are enforced per card independently. You can update them at any time — see [Spending limits](#spending-limits) below.

Omitting a limit means no limit is applied for that time window.

***

## Funding the account

All cards draw from a shared **holding wallet**. Before cards can transact you must fund this wallet with USDC on Polygon.

Retrieve the holding wallet deposit address via [Get holding balance](/api-reference/cards/holding/get-balance). The minimum deposit is **10 USD**.

<Warning>
  A minimum balance is always locked in the holding wallet to preserve capacity for at least one transaction. Withdrawals that would breach this floor are rejected.
</Warning>

To return funds to your treasury, use [Withdraw from holding](/api-reference/cards/holding/withdraw).

For cards using `TOPUP` approval, each card also has a **personal deposit wallet**. Fetch those addresses with [Get card top-up wallets](/api-reference/cards/virtual-cards/get-card-top-up-wallets). Deposits sent to these wallets are attributed to that specific card and used to settle its purchases.

***

## Fees wallet

The commissions charged on card activity — the fees applied to deposits and transactions — accumulate in a dedicated **fees wallet** on Polygon, separate from the holding wallet that funds card spending.

<Note>
  You can both **view the balances** and **make withdrawals** from the CryptoMate Portal (Cards → Summary → **Accumulated fees**), as well as through the API described below.
</Note>

### Pending vs. available balance

The fees wallet tracks two balances, visible in the Portal (Cards → Summary → **Accumulated fees**):

| Balance                  | Meaning                                                                                                                                                                               |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Pending to credit**    | Fees already charged but not yet settled on-chain into the fees wallet. A virtual balance that becomes available progressively as fees are collected from card deposits and spending. |
| **Available (on-chain)** | Fees already settled on-chain in the fees wallet. **Only this balance can be withdrawn.**                                                                                             |

### Withdrawing fees

Use [Withdraw fees](/api-reference/cards/account/withdraw-fees-wallet) to send accumulated fees to one of your wallets. Withdrawals draw only from the **available on-chain balance** and are made per token (`token_symbol`).

The destination must be a **whitelisted address enabled for at least 24 hours**:

<Warning>
  A newly whitelisted address cannot receive a fees withdrawal until **24 hours** after it was added. This delay is a security measure against unauthorized address changes.
</Warning>

* Manage the whitelist from the Portal (Cards → **Configuration**).
* List the addresses currently eligible (enabled ≥ 24 h) with [Get fees wallet whitelisted addresses](/api-reference/cards/account/get-fees-wallet-whitelisted-addresses).

Fees withdrawals are also available from the Portal (Cards → Summary → Accumulated fees → **Withdraw fees**). Each withdrawal is recorded in the transaction history as a `CLIENT_FEES_WITHDRAW` movement.

***

## Managing cards

### Spending limits

Update per-card daily, weekly, and monthly limits independently with [Update card limits](/api-reference/cards/virtual-cards/set-limits). Changes take effect immediately on the next authorization.

### Freeze and unfreeze

Use [Freeze or unfreeze card](/api-reference/cards/virtual-cards/set-frozen) to temporarily block a card. A frozen card declines all purchase attempts until unfrozen. The card state moves between `ACTIVE` and `FROZEN` without losing its configuration.

Useful for: temporary employee suspension, suspicious activity hold, cardholder request.

### Unblocking after a velocity block

If a [velocity rule](#velocity-rules) triggers, the card is automatically moved to `BLOCKED`. Manually unblock it with [Unblock card](/api-reference/cards/virtual-cards/unblock-card). Unblocking also resets the authorization counter so the card can transact immediately.

### Reissuing a card

[Reissue card](/api-reference/cards/virtual-cards/reissue-card) generates a new card number and CVV while keeping the same cardholder configuration, limits, and approval method. Use this when a card number is compromised. The old card is deactivated.

### Updating contact information

| What                    | Endpoint                                                        |
| ----------------------- | --------------------------------------------------------------- |
| Email for notifications | [Update email](/api-reference/cards/virtual-cards/update-email) |
| Phone for OTP / 3DS SMS | [Update phone](/api-reference/cards/virtual-cards/update-phone) |
| Card PIN                | [Update PIN](/api-reference/cards/virtual-cards/update-pin)     |

### Rotating the deposit wallet

If a `TOPUP` card's deposit wallet address needs to be rotated (e.g. for compliance or security), use [Rotate deposit wallet](/api-reference/cards/virtual-cards/rotate-deposit-wallet). A new address is generated and associated with the card. The old address stops accepting deposits.

### Deleting a card

[Delete card](/api-reference/cards/virtual-cards/delete-card) permanently deactivates the card. Any remaining balance in the card's individual wallet is returned to the holding wallet. This action is irreversible.

***

## 3DS authentication

3DS adds cardholder verification to e-commerce purchases. Two modes are available per card:

| Mode      | Behavior                                                                                                 |
| --------- | -------------------------------------------------------------------------------------------------------- |
| `sms`     | A one-time code is sent to the cardholder's registered phone.                                            |
| `webhook` | A webhook is sent to your endpoint with the OTP challenge. Your system delivers it via your own channel. |

Configure the mode with [Set 3DS configuration](/api-reference/cards/virtual-cards/set-3ds-configuration).

When a 3DS challenge fires, a `notification_3ds_authorization` webhook is delivered to your endpoint. For `webhook` mode, use [Respond to 3DS authorization](/api-reference/cards/virtual-cards/respond-3ds-authorization) to submit the OTP entered by the cardholder.

***

## Fraud protection

### Velocity rules

Velocity rules define rate limits at the **account level**, applied per individual card. They protect against card probing and rapid fraudulent use.

Each rule specifies:

* `max_authorizations` — the maximum number of **approved** authorizations allowed
* `time_window_seconds` — the sliding window over which the count is measured

You can configure up to **5 rules**. When any rule is breached, the transaction is declined and the card is automatically blocked. Unblocking the card also resets its authorization counter, ensuring the card can resume normal operation immediately.

Manage rules with:

* [Get velocity rules](/api-reference/cards/account/get-velocity-rules)
* [Replace velocity rules](/api-reference/cards/account/replace-velocity-rules) — replaces the entire ruleset atomically
* [Delete velocity rules](/api-reference/cards/account/delete-velocity-rules) — removes all rules

Example ruleset — no more than 3 purchases per minute, or 20 per hour:

```json theme={null}
{
  "rules": [
    { "max_authorizations": 3, "time_window_seconds": 60 },
    { "max_authorizations": 20, "time_window_seconds": 3600 }
  ]
}
```

When a velocity block fires, a [`card_blocked_by_velocity`](/integration/webhooks#card_blocked_by_velocity-card-blocked-by-velocity-rule) webhook is sent to your endpoint so your systems can react in real time (alert the cardholder, open a fraud investigation, etc.).

### Risk score engine

The risk score engine evaluates every purchase in real time. It assigns a numeric **score** by combining up to six signals, each weighted independently. If the score reaches or exceeds a configurable **threshold**, the transaction is declined.

#### How the score is calculated

Each signal is binary (0 or 1). The final score is the weighted sum:

```
score = (signal_geo × w_geo)
      + (signal_mcc × w_mcc)
      + (signal_amount × w_amount)
      + (signal_time × w_time)
      + (signal_declines × w_declines)
      + (signal_country × w_country)
```

A transaction is **rejected** when `score ≥ threshold`.

#### Signals

| Signal                   | ID                 | Fires (= 1) when…                                                                                      | Notes                                                              |
| ------------------------ | ------------------ | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------ |
| Impossible travel        | `geo_distance`     | Card used in a different country less than **4 hours** after the previous transaction                  | Compares merchant country of current vs. last approved transaction |
| Unfamiliar MCC           | `mcc_profile`      | Merchant category code was never seen in the card's **90-day history**                                 | Requires ≥ 5 historical transactions to activate                   |
| Amount above baseline    | `amount_baseline`  | Purchase amount exceeds the **95th percentile** of the card's historical amounts                       | Requires ≥ 5 historical transactions to activate                   |
| Unusual hour             | `time_window`      | Transaction hour appears in **less than 5%** of the card's historical transactions                     | Requires ≥ 5 historical transactions to activate                   |
| High decline rate        | `decline_rate`     | **3 or more** transactions were declined on this card in the last **24 hours**                         | Detects rapid retry / card probing                                 |
| Foreign merchant country | `merchant_country` | Merchant's country differs from the cardholder's country (set via `metadata.country` at card creation) | Signal is 0 if `metadata.country` is not set                       |

<Note>
  Signals that require a minimum history return 0 (no contribution) until the card has enough approved transactions. A brand-new card is only evaluated by `geo_distance`, `decline_rate`, and `merchant_country`.
</Note>

#### Configuration

The engine is configured at the account level from the Portal (Cards → Configuration → Risk Score). Each weight can be set to `0` to disable that signal entirely. Setting all weights to `0` disables the engine for the whole account.

| Field                     | Description                                                                           |
| ------------------------- | ------------------------------------------------------------------------------------- |
| `threshold`               | Score at or above which a transaction is rejected. Range: `0.0` – any positive value. |
| `geo_distance_weight`     | Weight for the impossible travel signal.                                              |
| `mcc_profile_weight`      | Weight for the unfamiliar MCC signal.                                                 |
| `amount_baseline_weight`  | Weight for the above-P95 amount signal.                                               |
| `time_window_weight`      | Weight for the unusual hour signal.                                                   |
| `decline_rate_weight`     | Weight for the high recent decline rate signal.                                       |
| `merchant_country_weight` | Weight for the foreign merchant country signal.                                       |

#### Examples

**Conservative setup** — only block clear anomalies, high threshold:

```json theme={null}
{
  "threshold": 0.8,
  "geo_distance_weight": 0.5,
  "mcc_profile_weight": 0.2,
  "amount_baseline_weight": 0.2,
  "time_window_weight": 0.1,
  "decline_rate_weight": 0.4,
  "merchant_country_weight": 0.0
}
```

In this configuration a transaction is rejected only if, for example, both impossible travel (0.5) and high decline rate (0.4) fire simultaneously (score = 0.9 ≥ 0.8). A single signal is not enough to reach the threshold.

**Strict setup** — any single anomaly blocks the transaction:

```json theme={null}
{
  "threshold": 0.3,
  "geo_distance_weight": 1.0,
  "mcc_profile_weight": 0.5,
  "amount_baseline_weight": 0.5,
  "time_window_weight": 0.3,
  "decline_rate_weight": 1.0,
  "merchant_country_weight": 0.3
}
```

Here, impossible travel alone (1.0) exceeds the threshold. Even an unusual hour (0.3) is enough to reject.

**Disabled engine** — all weights set to 0, no transaction is ever rejected by risk score:

```json theme={null}
{
  "threshold": 1.0,
  "geo_distance_weight": 0.0,
  "mcc_profile_weight": 0.0,
  "amount_baseline_weight": 0.0,
  "time_window_weight": 0.0,
  "decline_rate_weight": 0.0,
  "merchant_country_weight": 0.0
}
```

#### Fail-safe behavior

The engine is designed to fail open: if the transaction history cannot be fetched, or if the configuration cannot be loaded, the risk score check is skipped and the transaction proceeds normally. This ensures that a Redis or database hiccup never causes unexpected declines.

***

### Risk score fuse

The risk score engine evaluates each purchase and may decline transactions that appear high-risk. When a trusted cardholder is incorrectly blocked (false positive), you can arm a **one-shot fuse** that bypasses risk evaluation for the **next single purchase** on that card. After that purchase fires, the fuse is automatically consumed and normal validation resumes.

<Note>
  The fuse bypasses only the risk score check. All other controls (spending limits, velocity rules, frozen status, holding balance) still apply.
</Note>

| Operation              | Endpoint                                                                            |
| ---------------------- | ----------------------------------------------------------------------------------- |
| Arm the fuse           | [Arm risk score fuse](/api-reference/cards/virtual-cards/arm-risk-score-fuse)       |
| Disarm before it fires | [Disarm risk score fuse](/api-reference/cards/virtual-cards/disarm-risk-score-fuse) |
| Check fuse state       | [Get risk score fuse state](/api-reference/cards/virtual-cards/get-risk-score-fuse) |

***

### Blocked merchant categories

Block purchases based on the **type of business** the merchant runs — its merchant category. You keep a **blocklist of categories**, and any purchase from a merchant in one of those categories is automatically declined. Use it to keep company spending away from business types you never want your cards used for — for example, gambling and casinos, or cash advances and ATM withdrawals.

<Note>
  This control applies to **company cards** only. It is set once at the account level and enforced across every card your company issues. It does not apply to individual cards.
</Note>

Manage the blocklist from the Portal (Cards → **Configuration**), the same place where you manage country blocking. You choose categories by name from a standard catalog — there are no codes to type in.

On top of your own list, **CryptoMate maintains a platform-wide list of blocked categories** that always applies to every company. These platform categories are shown in the Portal for reference and **cannot be removed** — your list is added on top of them, never replacing them.

How the block behaves:

* If a purchase comes from a merchant whose category is on your blocklist — or on the platform-wide list — it is **declined**.
* A category blocked by the platform stays blocked even when it is not on your own list.

***

### Blocked merchant countries

Block purchases based on the country where the merchant is located. You keep a **blocklist of countries**, and any purchase from a merchant in one of those countries is automatically declined. Use it as a geographic fraud and security control — for example, to keep spending inside the regions where your business actually operates and shut out purchases from countries you never expect to transact in.

<Note>
  This control applies to **company cards** only. It is set once at the account level and enforced across every card your company issues. It does not apply to individual cards.
</Note>

Manage the blocklist from the Portal (Cards → **Configuration**), the same place where you manage merchant category (MCC) blocking. Add or remove countries at any time; changes take effect on the next purchase. Countries are identified by their standard two-letter country codes (for example, `US` or `AR`).

How the block behaves:

* If a purchase comes from a merchant whose country is on your blocklist, it is **declined** — the reason reported is "merchant country blocked".
* If a purchase does not carry a merchant country, it cannot be evaluated against the list and is **not** blocked by this control.

<Note>
  Blocked countries and blocked merchant categories (MCC) are **independent, additive controls**. A purchase is declined if it matches **either** list — neither one overrides the other.
</Note>

***

## Transactions

### Searching transactions

[Search transactions](/api-reference/cards/transactions/search-transactions) returns the transaction history for your account with filtering by card, date range, status, and more.

[Get transaction](/api-reference/cards/transactions/get-transaction) returns the full detail of a single transaction by ID.

### Accumulated spending

[Get accumulated spending](/api-reference/cards/transactions/get-accumulated-spending) returns the total amount spent within a given period, useful for dashboards and limit management.

### PDF statements

[Export transactions PDF](/api-reference/cards/transactions/get-transactions-pdf) generates a downloadable statement for a date range.

***

## Webhooks

Cards is the most event-heavy product. Register your webhook URL and `webhook_key` from the Portal (Settings → Webhooks) or via [Subscribe webhook URL](/api-reference/management/company/subscribe-webhook-url) and [Subscribe webhook key](/api-reference/management/company/subscribe-webhook-key).

All card events arrive with `"product": "cards"` in the envelope.

| Event                            | When it fires                                                                                                                                            |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `authorization`                  | A purchase needs your approval (WEBHOOK mode). Respond within **1,200 ms** with `"00"` / `"SUCCESS"` to approve or `"05"` to decline. Timeout = decline. |
| `authorized`                     | A purchase was approved (TOPUP / NONE mode, or your webhook approved it).                                                                                |
| `cleared`                        | An authorized purchase cleared and funds settled.                                                                                                        |
| `declined`                       | A purchase was declined (by your webhook, by velocity rules, by risk score, or by insufficient balance).                                                 |
| `reversal`                       | An authorized purchase was reversed by the merchant or network.                                                                                          |
| `refund`                         | A merchant refund was applied to the card.                                                                                                               |
| `deposit`                        | Funds arrived at a card's top-up wallet.                                                                                                                 |
| `visa_direct_deposit`            | A Visa Direct deposit credited the card.                                                                                                                 |
| `warranty_withdraw`              | A withdrawal from the holding balance completed.                                                                                                         |
| `notification_3ds_authorization` | A 3DS challenge was triggered. Deliver the OTP to the cardholder.                                                                                        |
| `card_blocked_by_velocity`       | A velocity rule triggered and blocked the card. Sent once per `ACTIVE → BLOCKED` transition.                                                             |

See [Webhooks](/integration/webhooks) for the full envelope format, authentication via `X-Webhook-Key`, and payload examples.

***

## Quick reference

| Goal                           | Endpoint                                                                                                                   |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| Issue a card                   | [POST /cards/virtual-cards/create](/api-reference/cards/virtual-cards/create-card)                                         |
| List all cards                 | [GET /cards/virtual-cards](/api-reference/cards/virtual-cards/list-cards)                                                  |
| Get a card                     | [GET /cards/virtual-cards/{cardId}](/api-reference/cards/virtual-cards/get-card)                                           |
| Update spending limits         | [PATCH /cards/virtual-cards/{cardId}/limits](/api-reference/cards/virtual-cards/set-limits)                                |
| Freeze / unfreeze              | [PATCH /cards/virtual-cards/{cardId}/frozen](/api-reference/cards/virtual-cards/set-frozen)                                |
| Unblock after velocity         | [POST /cards/virtual-cards/{cardId}/unblock](/api-reference/cards/virtual-cards/unblock-card)                              |
| Reissue card number            | [POST /cards/virtual-cards/{cardId}/reissue](/api-reference/cards/virtual-cards/reissue-card)                              |
| Check holding balance          | [GET /cards/holding/balance](/api-reference/cards/holding/get-balance)                                                     |
| Withdraw from holding          | [POST /cards/holding/withdraw](/api-reference/cards/holding/withdraw)                                                      |
| List fees withdrawal addresses | [GET /cards/account/fees-wallet/whitelisted-addresses](/api-reference/cards/account/get-fees-wallet-whitelisted-addresses) |
| Withdraw fees                  | [POST /cards/account/fees-wallet/withdraw](/api-reference/cards/account/withdraw-fees-wallet)                              |
| Configure velocity rules       | [PUT /cards/account/configuration/velocity-rules](/api-reference/cards/account/replace-velocity-rules)                     |
| Arm risk score fuse            | [POST /cards/virtual-cards/{cardId}/risk-score-fuse](/api-reference/cards/virtual-cards/arm-risk-score-fuse)               |
| Search transactions            | [GET /cards/transactions](/api-reference/cards/transactions/search-transactions)                                           |

<Card title="Cards API reference" icon="terminal" href="/api-reference/cards/index" horizontal>
  Explore endpoints for virtual cards, transactions, holding, and account configuration.
</Card>
