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

# Testing Cards

> Run the whole card lifecycle in sandbox: activation, issuance, funding, purchases, and refunds

<Warning>
  **Cards is available in sandbox only while we finish development.** Dakota enables Cards per
  account. The Cards endpoints are in the [API reference](/api-reference/introduction), marked
  **Sandbox only**. Endpoints, fields, and flows can still change before release.
</Warning>

Sandbox runs the real card code: authorizations are decided as in production, holds land on the wallet, and the same webhooks fire. Only the trigger is simulated. A simulation call stands in for the merchant and the card network.

```mermaid theme={null}
flowchart LR
    A["Activate a customer"] --> B["Create a cardholder"] --> C["Enable a wallet"] --> D["Create a card"]
    D --> E["Fund the wallet"] --> F["Simulate a purchase"] --> G["Clear, void, or refund it"]
```

## 1. Set up

1. Ask Dakota to activate Cards on your sandbox account. No agreements are needed.
2. [Activate a customer](/documentation/cards/activation). You act as the customer: open the terms link and accept it yourself.
3. [Create a cardholder](/documentation/cards/cardholders), [enable a wallet](/documentation/cards/wallet-enablement), and [create a card](/documentation/cards/issuing). These steps are the same as in production.

## 2. Fund the wallet

[`POST /sandbox/wallets/{wallet_id}/faucet`](/api-reference/sandbox/fund-a-sandbox-wallet-from-the-testnet-faucet) sends testnet RD to the wallet on Base Sepolia, through the normal deposit path.

```json theme={null}
POST /sandbox/wallets/{wallet_id}/faucet
X-Idempotency-Key: 9e2f1a3b-4c5d-4e6f-8a7b-1c2d3e4f5a6b

{ "asset": "RD", "amount": "2.00" }
```

It returns a `simulation_id`. Poll [`GET /sandbox/simulations/{simulation_id}`](/api-reference/sandbox/get-simulation-status) until the funds land.

A hold can be larger than the purchase, so fund more than you plan to spend. Two faucet calls cover a 2 USD purchase.

## 3. Simulate a purchase

[`POST /sandbox/cards/simulate/transaction`](/api-reference/sandbox/simulate-a-card-authorization):

```json theme={null}
POST /sandbox/cards/simulate/transaction
X-Idempotency-Key: 3a4b5c6d-7e8f-4a1b-9c2d-3e4f5a6b7c8d

{
  "card_id": "2tQRvvnYkN6edEJUTmF1LzTj2ug",
  "amount": "2.00",
  "merchant": { "descriptor": "COFFEE ROASTERS", "mcc": "5814", "country": "USA" },
  "type": "authorization"
}
```

The response names the `card_transaction_id`, and `card_transaction.created` fires.

* `type` is `authorization` (default), `financial_authorization` (clears immediately), or `balance_inquiry` (moves no funds, takes no `amount`).
* `partial_approval_capable: true` simulates a merchant that accepts a partial approval.
* **A decline is not an HTTP error.** It creates a card transaction with `status: declined` and a `decline_reason`. To trigger one, simulate a purchase on an unfunded wallet.
* A card that is not `active` cannot present a purchase: the call returns `409 card-not-active`.

## 4. Advance the purchase

[`POST /sandbox/cards/simulate/transaction/{card_transaction_id}`](/api-reference/sandbox/advance-a-simulated-card-transaction):

```json theme={null}
POST /sandbox/cards/simulate/transaction/{card_transaction_id}
X-Idempotency-Key: 4b5c6d7e-8f9a-4b2c-8d3e-4f5a6b7c8d9e

{ "action": "clear", "amount": "2.00" }
```

| `action` | Effect | `amount` |
| - | - | - |
| `clear` | Settles the authorization. | Optional, for a partial clearing or an over-capture. |
| `void` | Releases the authorization. | Optional, for a partial reversal. |
| `expire` | Lets the authorization lapse. | Not allowed. |
| `update_amount` | Changes the held amount. | Required. |
| `return` | Refunds the cardholder. | Required. |
| `return_reversal` | Reverses a return. | Not allowed. |

A return is a **new** transaction on the same card, and the response names it. To reverse the return, advance that new transaction.

## Limits

| Limit | When you exceed it |
| - | - |
| 2 USD per call, for simulations and the faucet | `422` |
| A daily allowance of card simulations per account | `429`. It restores within 24 hours. |
| Faucet calls per wallet and per account, per day | A distinct problem type for each limit |
| One idempotency key per simulation | The same key returns the same simulation. With different parameters, or after the simulation failed, it returns `409`: use a new key. |

Simulation endpoints return `403` in production.
